算法 贪心5 || 435. 无重叠区间 763.划分字母区间 56. 合并区间 738.单调递增的数字 968.监控二叉树

435. 无重叠区间

和452. 用最少数量的箭引爆气球 思路是很相似的。本题按照左边排序或者按照右边排序都是可以的,最终目的都是为了让区间尽可能重叠。
1、按右边排序,排序完第一个元素的右边界一定是最小右边界。往下找第一个不与其重合的左边界,找的话count+1。在找到4之前,1 2 3中最小右边界(最不容易与后面左边界重合的值,一定是1的右边界)
算法 贪心5 || 435. 无重叠区间 763.划分字母区间 56. 合并区间 738.单调递增的数字 968.监控二叉树_第1张图片

class Solution {
public:
    static bool cmp(const vector<int>& v1,const vector<int>& v2){
        return v1[1] < v2[1];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        sort(intervals.begin(),intervals.end(),cmp);
        int count = 1;
        int end = intervals[0][1];
        for(int i = 1; i < intervals.size(); ++i){
            if(intervals[i][0] >= end){
                count++;
                end = intervals[i][1];
            }
        }
        return intervals.size() - count;
    }
};

2、按左边界排序。
根据右边界排序,一下子就能找到下一个不重合的区域是4。但是按照左边界的排序,找的是重合区域。
算法 贪心5 || 435. 无重叠区间 763.划分字母区间 56. 合并区间 738.单调递增的数字 968.监控二叉树_第2张图片

class Solution {
public:
    static bool cmp(const vector<int>& v1,const vector<int>& v2){
        return v1[0] < v2[0];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        sort(intervals.begin(),intervals.end(),cmp);
        int count = 0;
        int end = intervals[0][1];
        for(int i = 1; i < intervals.size(); ++i){
            if(intervals[i][0] < end){
                count++;
                end = min(end,intervals[i][1]);
            }
            else{
                end = intervals[i][1];
            }
        }
        return count;
    }
};

763.划分字母区间

之前做过,直接能想到方法。但是!要注意更新maxindex要在收获结果之前!因为要设置maxindex的初始值。如果是INT_MIN,但是cdaa这种情况,先收获结果的话,就会漏掉index = 0,c单独分割的情况。

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> res;
        unordered_map<char, int> map;
        int maxIndex = INT_MIN;
        for (int i = 0; i < s.size(); ++i) {
            map[s[i]] = i;
        }
        for(int i = 0; i < s.size(); ++i){
            if(map[s[i]] > maxIndex) maxIndex = map[s[i]];
            if(i == maxIndex){
                int sum = 0;
                for(int a : res) sum += a;
                int temp = i + 1 - sum;
                res.push_back(temp);
                
            }
        }
        return res;
    }
};

56. 合并区间

和452. 用最少数量的箭引爆气球 (opens new window) 和 435. 无重叠区间 (opens new window) 都是一个套路。
卡哥直接在res数组里融合区间,更简洁一些

result.back()[1] = max(result.back()[1], intervals[i][1]); 

自己的方式是通过left和right来记录重叠区间

class Solution {
public:
    static bool cmp(const vector<int>& v1, const vector<int>& v2){
        return v1[0] < v2[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> res;
        sort(intervals.begin(),intervals.end(),cmp);
        int left = intervals[0][0];
        int right = intervals[0][1];
        for(int i = 1; i < intervals.size(); ++i){
            if(intervals[i][0] <= right){
                right = max(right,intervals[i][1]);
            }
            else{
                vector<int> vec;
                vec.push_back(left);
                vec.push_back(right);
                res.push_back(vec);
                left = intervals[i][0];
                right = intervals[i][1];
            }
        }
        vector<int> vec;
        vec.push_back(left);
        vec.push_back(right);
        res.push_back(vec);
        return res;
    }
};

738.单调递增的数字

本质是从后向前遍历,到第一个满足升序的位置,减一,然后后面的数置为9。比如322变成299。但是在处理方式上,如果遇到100,用数组处理就很非常麻烦,会遇到位数缩减的问题。**string有一个函数stoi,可以将string转换成int。**会自动去除无效位数。所以可以将数字先通过to_string转成字符串处理。处理完以后再转为int

class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string str = to_string(n);
        int index = str.size();
        for(int i = str.size() - 1; i > 0; --i){
            if(str[i] < str[i-1]){
                index = i;
                str[i-1]--;
            }
        }
        for(int i = index; i < str.size(); ++i){
            str[i] = '9';
        }
        return stoi(str);
    }
};

968.监控二叉树

想到了后序遍历,也想到子节点的父节点给摄像头。但是考虑并不周全。本题可以使用状态转移。
一个节点可能处于三种情况下:
1、没覆盖:0
2、有相机:1
3、有覆盖:2
算法 贪心5 || 435. 无重叠区间 763.划分字母区间 56. 合并区间 738.单调递增的数字 968.监控二叉树_第3张图片

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int count = 0;
    int minCameraCover(TreeNode* root) {
        if(find(root) == 0){
            count++;
        }
        return count;
    }
    int find(TreeNode* cur){
        if(cur == nullptr) return 2;
        int left = find(cur->left);
        int right = find(cur->right);
        if(left == 2 && right == 2) return 0;
        if(left == 0 || right == 0) {
            count++;
            return 1;
        }
        if(left == 1 || right == 1) return 2;
        return -1;
    }
};

你可能感兴趣的:(算法,排序算法,数据结构)