贪心算法之区间问题总结

贪心算法之区间问题总结_第1张图片

一、跳跃游戏

跳跃游戏类的问题,不关心每一步怎么跳,只需要关心最大覆盖范围

这里注意i是在当前最大可覆盖范围内遍历,如{2,1,0,1},就是在0~2范围内遍历,千万不能0~numsSize-1范围内遍历!!!

bool canJump(int* nums, int numsSize){
    //不关心每一步怎么跳,只需要关心最大覆盖范围
    int cover=0;
    for(int i=0;i<=cover;i++){
        cover=fmax(cover,nums[i]);
        if(cover>=numsSize-1) return true;
    }
    return false;
}

二、跳跃游戏II

没见过不好想,建议记下来

关键是当前覆盖范围和下一步覆盖范围都要考虑

计算下一步覆盖范围的目的是用来更新当前覆盖范围,以保证跳跃步数最少

int jump(int* nums, int numsSize){
    //统计两个覆盖范围:当前这一步的最大覆盖和下一步最大覆盖
    //如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,
    //那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点
    if(numsSize==1) return 0;
    int curCover=0,nextCover=0;
    int result=0;
    for(int i=0;i<=curCover;i++){
        nextCover=fmax(nextCover,i+nums[i]);
        if(i==curCover){
            if(curCover=numsSize-1) break;
            }else break;
        }
    }
    return result;
}

三、无重叠区间

区间重叠类问题第一步:排序

区间判断重叠方法:若当前区间的右边界大于下一个区间的左边界,则表示有重叠

合并实质上就是更新当前区间的右边界

class Solution {
private:
    static bool cmp(const vector &a,const vector &b){
        return a[0]>& intervals) {
        //按照区间左边界从小到大排序
        //若当前区间的右边界大于下一个区间的左边界,则表示有重叠
        //可以把移除理解成一种特殊的合并,所有重叠区间合并之后,右边界为最小的那个
        if(intervals.size()==1) return 0;
        sort(intervals.begin(),intervals.end(),cmp);
        int result=0;
        for(int i=1;iintervals[i][0]){
                intervals[i][1]=fmin(intervals[i-1][1],intervals[i][1]);
                result++;
            }
        }
        return result;
    }
};

四、用最少数量的箭引爆气球

实际上这题就是在问:有多少组无重叠区间,和上题都在研究重叠与无重叠区间的问题

注意本题的重叠区间内的所有区间的右边界和上题一样,也要更新为重叠区间里最小的右边界

因为找最大重叠个数的重叠区间看的是“短板”!!!

class Solution {
private:
    static bool cmp(const vector &a,const vector &b){
        return a[0]>& points) {
        if(points.size()==1) return 1;
        sort(points.begin(),points.end(),cmp);
        int result=1;
        for(int i=1;i

五、划分字母区间

本题实际上就是在问:求每个闭包的长度

所以关键就是,怎么判断闭包的起始位置

这就和跳跃游戏II有点像了~

class Solution {
public:
    vector partitionLabels(string s) {
        //开辟一个数组记录每个字母的最后出现位置
        int cover[27];
        for(int i=0;i result;
        for(int i=0;i

六、合并区间

所谓合并区间,其实就是重叠区间的右边界取重叠区间内最大右边界

如果下一个区间和当前重叠区间重叠,则更新当前重叠区间的右边界;

若不重叠,说明是新的闭包,上一个重叠区间更新完成,插入result新的重叠区间

class Solution {
private:
    static bool cmp(const vector &a,const vector &b){
        return a[0]> merge(vector>& intervals) {
        //所谓合并区间,其实就是重叠区间的右边界取重叠区间内最大右边界
        //如果下一个区间和当前重叠区间重叠,则更新当前重叠区间的右边界;
        //若不重叠,说明是新的闭包,上一个重叠区间更新完成,插入result新的重叠区间
        if(intervals.size()==1) return intervals;
        sort(intervals.begin(),intervals.end(),cmp);
        vector> result;
        result.push_back(intervals[0]);
        for(int i=1;i=intervals[i][0])
                result.back()[1]=max(intervals[i][1],result.back()[1]);
            else
                result.push_back(intervals[i]);
        }
        return result;
    }
};

你可能感兴趣的:(代码随想录,贪心算法,算法,leetcode)