代码随想录算法训练营day30

5 阅读2分钟

406 根据身高重建队列 1.同分发糖果对比,依旧存在两条比较链路,一是身高比较,二是前面有多少个较高人比较 2.使用sort函数时要注意设计比较器 3.不能两种比较因素同时考虑,应当先选择一个进行排序满足,达成局部最优,然后接着处理第二个比较条件,从局部最优达成全局最优


class Solution {
public:
//设置比较器
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[0] == b[0]) return a[1] < b[1];
        return a[0] > b[0];
    }
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort (people.begin(), people.end(), cmp);
        list<vector<int>> que; // list底层是链表实现,插入效率比vector高的多
        for (int i = 0; i < people.size(); i++) {
            int position = people[i][1]; // 插入到下标为position的位置
            std::list<vector<int>>::iterator it = que.begin();
            while (position--) { // 寻找在插入位置
                it++;
            }
            que.insert(it, people[i]);
        }
        return vector<vector<int>>(que.begin(), que.end());
    }
};
  1. 用最少数量箭引爆气球 1.理解此处的局部最优!!!通过不断更新右边界达到局部最优条件 2.学会设计比较器

class Solution {
public:
    //设计比较器
    static bool cmp(const vector<int>& a,const vector<int>& b){
        return a[0]<b[0];
    }
    int findMinArrowShots(vector<vector<int>>& points) {
        //排除特殊情况
        if(points.size()==0) return 0;
        //对气球进行排序
        sort(points.begin(),points.end(),cmp);
        //设计arrow存储箭的数量
        int arrow=1;//必有第一个气球
        for(int i=1;i<points.size();i++){//从第二个球开始
            if(points[i][0]>points[i-1][1]){//前一个气球的右边界小于当前气球的左边界
                arrow++;
            }
            else{
                points[i][1]=min(points[i][1],points[i-1][1]);//更新局部的气球右边界
            }
        }
        return arrow;
    }
};

435.无重叠区间 1.本题类似最少数量箭射爆气球,首先要对区间按照边界进行排序,根据选择的边界设计比较器 2.本题的局部最优依然是不断更新右边界,当不重叠时,更新为最新的右边界并计数。

class Solution {
public:
    //设计比较器
    static bool cmp(vector<int>& a,vector<int>& b){
        return a[1]<b[1];//使用右边界排序
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if(intervals.size()<=1) return 0;
        sort(intervals.begin(),intervals.end(),cmp);//对所有区间,按照右边界进行排序
        int count=1;//记录不重叠的区间数量
        int end = intervals[0][1]; // 记录区间分割点
        for (int i = 1; i < intervals.size(); i++) {
            if (end <= intervals[i][0]) {
                end = intervals[i][1];
                count++;
            }
        }
        return intervals.size()-count;
    }
};

763

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int hash[27] = {0}; // i为字符,hash[i]为字符出现的最后位置
        for (int i = 0; i < s.size(); i++) { // 统计每一个字符最后出现的位置
            hash[s[i] - 'a'] = i;
        }
        vector<int> result;
        int left = 0;
        int right = 0;
        for (int i = 0; i < s.size(); i++) {
            right = max(right, hash[s[i] - 'a']); // 找到字符出现的最远边界
            if (i == right) {
                result.push_back(right - left + 1);
                left = i + 1;
            }
        }
        return result;
    }
};