正则表达式regex+数组去重+两熊分蜂蜜【动态规划】
正则表达式regex
还是要跟着例子结合看
例如:
-
runoo+b,可以匹配 runoob、runooob、runoooooob 等,+ 号代表前面的字符必须至少出现一次(1次或多次)。
-
runoo*b,可以匹配 runob、runoob、runoooooob 等,* 号代表前面的字符可以不出现,也可以出现一次或者多次(0次、或1次、或多次)。
-
colou?r 可以匹配 color 或者 colour,? 问号代表前面的字符最多只可以出现一次(0次或1次)。
菜鸟:https://www.runoob.com/regexp/regexp-syntax.html
\D元字符可以匹配非数字字符,等价于"[^0-9]"。
数组去重
unique函数的去重过程实际上就是不停的把后面不重复的元素移到前面来,也可以说是用不重复的元素占领重复元素的位置。
单纯的使用unique函数的话,容器的长度并没有发生变化,只是元素的位置发生了变化:【在使用前绝大数情况下需要对容器中的元素进行排序】
vector<int> a = {1,3,3,4,5,6,6,7}; vector<int>::iterator it_1 = a.begin(); vector<int>::iterator it_2 = a.end(); sort(it_1,it_2); cout<<"去重前的 a : "; for(int i = 0 ; i < a.size(); i++){ cout<<a[i]<<" "; }cout<<endl;// 1 3 3 4 5 6 6 7 unique(it_1,it_2); cout<<"去重后的 a : "; for(int i = 0 ; i < a.size(); i++){ cout<<a[i]<<" "; }// 1 3 4 5 6 7 6 7(没3了) //unique去重的过程是将重复的元素移到容器的后面去:不正确,应该是把不重复的元素移到前面来。 //和erase函数一起:new_end = unique(it_1,it_2); a.erase(new_end,it_2);
int a[10] = { 0, 7, 7, 6, 1, 1, 5, 5, 8, 9 }; int n = unique(a, a + 10) - a; //函数返回值不是去重后容器中元素的数量,而是去重后容器中的末地址。 //也就是说,如果想得到去重后容器中元素的数量的话还要减去初始地址 cout << n << endl;// 7:最后一个不重复数字的下标 for (int i = 0; i < 10; i++){ cout << a[i] << " "; // 0 7 6 1 5 8 9 5 8 9 } for (int i = 0; i < n; i++){ cout << a[i] << " "; // 0 7 6 1 5 8 9 }
unique函数通常和erase函数一起使用,来达到删除重复元素的目的。(注:此处的删除是真正的删除,即从容器中去除重复的元素,容器的长度也发生了变换;
#include<stdc++.h> using namespace std; int main() { vector<int> a ={1,3,3,4,5,6,6,7}; vector<int>::iterator it_1 = a.begin(); vector<int>::iterator it_2 = a.end(); vector<int>::iterator new_end; new_end = unique(it_1,it_2); //注意unique的返回值,去重后序列(这个序列不含有重复数值)的末尾的下一个元素 a.erase(new_end,it_2); cout<<"删除重复元素后的 a : "; for(int i = 0 ; i < a.size(); i++) cout<<a[i]; cout<<endl; }
erase()用法
//1. string容器所特有 删除容器中从pos位置开始的n个元素 string str = "hello world!"; cout<<str.erase(0,1)<<endl; //2. 删除容器中position所指位置的元素 string str = "hello world!"; string::iterator it_1 = str.begin(); str.erase(it_1); //3. 删除容器中first到last之间的所有元素(左闭右开) string str = "hello world!"; string::iterator it_1 = str.begin(); string::iterator it_2 = str.begin() + 1; str.erase(it_1,it_2); //以上都能使hello变成ello
Vector去重
vector<int> A;//vector:A.size();返回值是无符号整数 0-1会变大https://blog.csdn.net/h799710/article/details/109445906 //取元素值时通过下标A[i]或迭代器时的指针* A.push_back(1);A.push_back(2);A.push_back(1);A.push_back(2); A.push_back(2);A.push_back(2); //删除重复数据 for (vector<int>::iterator i = A.begin(); i != A.end() - 1; ++i) { for (vector<int>::iterator j = i + 1; j != A.end();++j) { cout<<*i<<" "<<*i; if (*i == *j) { j = A.erase(j); --j;//!! 向量erase()的删除时,返回值指向删除元素的下一个 待会还有++j呢 } } } //排序并删除重复 void elimDups(vector<string> &words) { sort(words.begin(),words.end()); auto end_unique = unique(words.begin(),words.end()); words.erase(end_unique,words.end()); } //删去指定的数值 int val = 4 || 7;//伪代码 vector<int>::iterator it; for(it=A.begin();it!=end();++it){ if(*it == val){ it = A.erase(it); --it;//!! } } for (int i = 0; i < A.size(); ++i) cout << A[i]; cout << endl;
计算数组中可构成三角形的个数
要想构成三角形,只需三角形中两条最短边之和大于最长边。
双指针法:
基于这样的原理,我们可以先将数组从小到大进行排序。将数组排序后,我们可以这样想,固定某一个数,然后用左右两个指针分别指向某个数,当左右指针指向的数字之和大于我们固定的数时,说明此种情况成立。然后将右指针向左移动一位继续判断直到不满足为止,将左指针向右移动一位继续判断;直到左指针跟右指针重合。根据这个思路,我们将数组从大到小遍历,将当前遍历的数nums[i]进行固定,让左指针指向第0个数nums[0],右指针指向这个数的左边一个数nums[i-1]。当nums[left]+nums[right]>nums[i]时,把右指针right固定,可以想到:当左指针left往右遍历时,左指针与右指针之间的和肯定也满足要求;因此有count+=(right-left)。【固定右指针 此时左指针到右中间这段都是满足条件的 所以直接count+=就行】
将右指针right往左移一位,继续进行判断,如果成立,则right继续重复前面操作;如果不成立,说明两个数之和太小了,此时将左指针left往右移一位,继续进行判断,直到left与right指针重合,这样就把nums[i]所有的情况都考虑了,最后数组遍历完结果就出来了
class Solution { public: int triangleNumber(vector<int>& nums) { int count = 0, size = nums.size();//由无符号转成int了 大胆-1 sort(nums.begin(), nums.end()); for (int i = size - 1; i >= 2; i--) { int left = 0, right = i - 1; while(left < right) { if (nums[left] + nums[right] > nums[i]) { count += (right - left); right--; } else { left++; } } } return count; } };
深信服笔试的要求不输出重复三角形:
1. 结构体xyz+bool:用malloc/new创建结构体数组,得到满足条件的所有三角形后,考虑删除:三条边全相等就不输出:将arr[i]三角形的三条边sort排序,之后A.x1==B.x1 && A.x2==B.x2 && A.x3==B.x3此种情况下相等再删除bool=false【不排序的话 2 3 4 3 2 4也是相同的哇】
2.结构体sort unique erase
//1. sort()改写 sort(first_pointer,first_pointer+n,cmp)默认升序 struct Student { char name[11]; int solve; int time; }p[10000]; bool cmp(const Student& a, const Student& b)//常量引用 { if (a.solve != b.solve) { if (a.solve > b.solve) return true; else return false; } else if (a.time != b.time) return a.time < b.time; else return (strcmp(a.name, b.name) < 0); } sort(p,p+n,cmp); //重载小于号 struct Student { string name; int MathGrade; int ChineseGrade; //重载小于号,语文成绩大的学生排在前面,结构体中的变量ChineseGrade bool operator< (const Student& tmp) const { return ChineseGrade > tmp.ChineseGrade; } }; sort(students, students+5);
两熊分蜂蜜
两熊分蜜吵架分家;
要求:
- 尽可能的重量均分,至少自己能少的最少;
- 在罐子数量上差距不能超过1。
输入描述:
- 每一行给出蜜罐的数量,2<= n <= 100
- 每蜜罐的重量 1< M <= 500
输出描述:两个数字A B 分别表示熊大和熊二能分到蜜的总重输入:344756249输出:305 447
一组数 如何分类 使得差值最小
动态规划--背包问题