[Code Random Record] Greedy Algorithm V

first question:

LeetCode official website - the technology growth platform loved by geeks around the world

 Learning record:

Similar to playing a balloon, end must be maintained as the min right interval every time, because only the smallest right boundary has the least impact on other intervals:

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.size() == 0) return 0;
        auto cmp = [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];};
        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(intervals[i][1], end);
            }
            else end = intervals[i][1]; //无重叠
        }
        return count;
    }
};

 Second question:

LeetCode official website - the technology growth platform loved by geeks around the world

Learning record:

Record the farthest position of all letters, and then traverse from the beginning. When the current subscript is equal to the farthest position of the current letter, it is the split point:

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int hash[27] = {0};
        for (int i = 0; i < s.size(); i++) {
            hash[s[i] - 'a'] = i; //相同的字母的index不断更新
        }
        vector<int> res;
        int left = 0, right = 0;
        for (int i = 0; i < s.size(); i++) {
            right = max(hash[s[i] - 'a'], right);
            if (right == i) {
                res.push_back(right - left + 1);
                left = i + 1; //切片以后left应指向下一个元素
            }
        }
        return res;
    }
};

 Question 3:

LeetCode official website - the technology growth platform loved by geeks around the world

 Already AC, it is the same routine as shooting balloons and non-overlapping intervals. First sort the vector<vector<int>> so that all adjacent intervals overlap as much as possible, and then determine the overlap:

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if (intervals.size() == 1) return intervals;
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, 
        const vector<int>& b){return a[0] < b[0];});
        int left = intervals[0][0], right = intervals[0][1];
        vector<vector<int>> res;
        res.push_back(vector<int>{left, right});
        for (int i = 0; i < intervals.size(); i++) {
            if (intervals[i][0] <= right) {
                right = max(right, intervals[i][1]);
                left = min(left, intervals[i][0]);
                res.pop_back();
            }
            else {
                right = intervals[i][1];
                left = intervals[i][0];
            }
            res.push_back(vector<int>{left, right});
        }
        return res;
    }
};

Code Capriccio modifies the value directly in res, which requires one less pop_back operation than mine:

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        if (intervals.size() == 0) return result; // 区间集合为空直接返回
        // 排序的参数使用了lambda表达式
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});

        // 第一个区间就可以放进结果集里,后面如果重叠,在result上直接合并
        result.push_back(intervals[0]); 

        for (int i = 1; i < intervals.size(); i++) {
            if (result.back()[1] >= intervals[i][0]) { // 发现重叠区间
                // 合并区间,只更新右边界就好,因为result.back()的左边界一定是最小值,因为我们按照左边界排序的
                result.back()[1] = max(result.back()[1], intervals[i][1]); 
            } else {
                result.push_back(intervals[i]); // 区间不重叠 
            }
        }
        return result;
    }
};

Guess you like

Origin blog.csdn.net/weixin_43785314/article/details/132371596