代码随想录Day13 贪心算法--3

452 用最少数量的箭引爆气球

如上图所示 我们可以先用每一个气球的左边界来对气球进行一个排序 然后我们就可以开始遍历整个序列 我们看当前气球的左边界是否大于前一个气球的右边界 如果大于 就说明两者不重叠 那么弓箭数就要加1 如果不大于 就说明两者重叠 此时我们应该更新一下重叠气球的最小右边界 也就是取两个气球右边界的最小值(因为可以存在【1,4】 【2,3】这样的情况)

class Solution {
    static bool cmp(const vector<int>& a,const vector<int>& b){
        return a[0] < b[0];
    }
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.size()==0){
            return 0;
        }
        int ans=1;
        sort(points.begin(),points.end(),cmp);
        for(int i=1;i<points.size();i++){
            if(points[i][0]>points[i-1][1]){
                ans++;
            }else{
                points[i][1]=min(points[i - 1][1], points[i][1]);
            }
        }
        return ans;
    }
};

435. 无重叠区间 

思路是一样的 如果有重叠区间 就让ans++ 并且将end更新到两个区间的最小值(因为右边界越小 重叠的可能性也就越小 所以我们用end来保存最小的右边界) 表示要删除区间 如果没有重叠 就要end更新到当前区间的右边界

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

763 划分字母区间

题意如上图所示 如果一个字母区间包含了字母a那么所有a都必须在这个区间里面出现 所以我们先记录下每一个字母出现的最大的下标 然后开始遍历字符串 用left和right表示左右边界并且不断的去更新right右边界 如果i遍历到right的地方 就截取这一区间 然后更新left的值

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;
        }
        vector<int> ans;
        int left=0,right=0;
        for(int i=0;i<s.size();i++){
            right=max(right,hash[s[i]-'a']);
            if(i==right){
                ans.push_back(right-left+1);
                left=i+1;
            }
        }
        return ans;
    }
};

56 合并区间 

这题思路和前面重叠区间的思路相似 都是先对区间左边进行排序 然后寻找是否有重叠区间 如果重叠就更新右边界 但是这一题的处理技巧不一样 是直接将要处理的区间放入ans数组 然后开始遍历判断当前区间和ans数组里最后的区间作比较 直接修改ans数组里面的区间 如果不重叠的话 就将当前区间放入ans数组

class Solution {
    static bool cmp(const vector<int>& a,const vector<int>& b){
        return a[0]<b[0];
    }
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> ans;
        sort(intervals.begin(),intervals.end(),cmp);
        if(intervals.size()==0){
            return ans;
        }
        ans.push_back(intervals[0]);
        for(int i=1;i<intervals.size();i++){
            if(intervals[i][0]<=ans.back()[1]){
                ans.back()[1]=max(ans.back()[1],intervals[i][1]);
            }else{
                ans.push_back(intervals[i]);
            }
        }
        return ans;
    }
};

738 单调递增的数字 

该题要求满足数字是单调递增的 所以很容易想到我们应该从后往前遍历 如果后面的数大于前面的数就不要做处理 如果后面的数小于前面的数 我们就需要把后面的数字变为9 然后前面的数字减1 因为这样是满足让整体最大(但是我们不能直接把后面数字变成9 需要用一个flag来记录从哪里往后需要变成9 因为只要一个位置的数要变成9 那么该位置后面的所有数字变成9是都成立的且是满足最大的 比如100这个例子 如果不标记flag得到的结果是90)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值