正则表达式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);
View Code
 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
    }
View Code

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;
 
}
View Code

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
View Code

 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;
View Code

 计算数组中可构成三角形的个数

要想构成三角形,只需三角形中两条最短边之和大于最长边。

双指针法:
基于这样的原理,我们可以先将数组从小到大进行排序。将数组排序后,我们可以这样想,固定某一个数,然后用左右两个指针分别指向某个数,当左右指针指向的数字之和大于我们固定的数时,说明此种情况成立。然后将右指针向左移动一位继续判断直到不满足为止,将左指针向右移动一位继续判断;直到左指针跟右指针重合。

根据这个思路,我们将数组从大到小遍历,将当前遍历的数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;
    }
};
View Code

深信服笔试的要求不输出重复三角形:

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);
View Code

 

 

 

 

 

两熊分蜂蜜

两熊分蜜吵架分家;

要求:
  1. 尽可能的重量均分,至少自己能少的最少;
  2. 在罐子数量上差距不能超过1。
输入描述:
  1. 每一行给出蜜罐的数量,2<= n <= 100
  2. 每蜜罐的重量 1< M <= 500
输出描述:两个数字A B 分别表示熊大和熊二能分到蜜的总重
输入:
3
447
56
249
输出:305 447

一组数 如何分类 使得差值最小

 

动态规划--背包问题

 

posted @ 2022-03-12 11:51  像走了一光年  阅读(96)  评论(0编辑  收藏  举报