Leetcode_8【贪心算法】//一刷完结

目录

455.分发饼干

376. 摆动序列

53. 最大子序和  

122.买卖股票的最佳时机 II

55.跳跃游戏

45.跳跃游戏 II

1005.K次取反后最大化的数组和  

134. 加油站 

135. 分发糖果 

 860.柠檬水找零 

406.根据身高重建队列 

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

435. 无重叠区间 

763.划分字母区间 

56. 合并区间  

738.单调递增的数字 

968.监控二叉树 (可以跳过)

总结 


455.分发饼干

力扣题目链接

代码随想录

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        int size = g.size();
        int index = s.size() - 1; // 饼干数组的下标
        int result = 0;
        sort(g.begin(), g.end());//注意排序!!
        sort(s.begin(), s.end());

        for(int i = size - 1; i >= 0; i--){//注意:遍历胃口
            if(g[i]<=s[index]){
                index--;
                result++;
            }
        }
        return result;
    }
};

我觉得先满足小胃口比较简单:

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int j = 0;
        for(int i = 0; i < s.size(); i ++){//fast--s
            if(j < g.size() && g[j] <= s[i]) j ++;//slow--g
        }
        return j;
    }
};

376. 摆动序列

代码随想录

力扣题目链接

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int legth = 1;//ATTENTION : 记录峰值个数,序列默认序列最右边有一个峰值
        int curDiff = 0; // 目前差值
        int preDiff = 0; // 前一对差值
        if(nums.size() <= 2) legth = nums.size();
        else{
            for(int i = 0; i < nums.size()-1; i++){
                curDiff = nums[i+1] - nums[i];
                if((preDiff <= 0 && curDiff >0 )|| (preDiff >= 0 && curDiff <0)){
                    legth++;
                    preDiff = curDiff;
                }
                //ATTENTION : 言外之意是,当p<=0 , c <=0时 与 p>=0, c>=0时不更新preDiff
            }
        }
        return legth;
    }
};

53. 最大子序和  

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int sum = 0;
        int res = INT_MIN; //如果这里是0就不对了,那么负数为输出0
        for(int i = 0; i < nums.size(); i++){
            sum += nums[i];

            //这两个顺序还不能反过来,要不还是处理不了-1
            res = res > sum ? res : sum;
            if(sum <= 0) sum = 0;
        }
        return res;
    }
};

122.买卖股票的最佳时机 II

力扣题目链接

代码随想录

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<int> diff;
        int res = 0;
        int size = prices.size();
        for(int i = 0; i < size - 1; i++){
            if(prices[i+1]-prices[i]>0){
                res += prices[i+1]-prices[i];
            }
        }
        return res;
    }
};

55.跳跃游戏

力扣题目链接

代码随想录

class Solution {
public:
    bool canJump(vector<int>& nums) {
        if(nums.size()==1) return true;
        int index = 0;
        for(int i = 0; i <= index; i++){//ATTENTION: i<=cover
            index = max(index, i + nums[i]);//新添加的cover
            if(index >= nums.size()) return true;
        }
        return false;
    }
};

二刷这样做的

class Solution {
public:
    bool canJump(vector<int>& nums) {
        if(nums.size() == 0) return false;
        int right = 0;
        for(int i = 0; i < nums.size(); i++){
            if(i > right) return false;
            right = right > i + nums[i] ? right : i + nums[i];
        }
        return true;
    }
};

45.跳跃游戏 II

力扣题目链接

class Solution {
public:
    int jump(vector<int>& nums) {
        int step = 0;
        int NextDistance = 0;
        int CurrentDistance = 0;
        for(int i = 0; i < nums.size(); i++){
            NextDistance = max(NextDistance,i + nums[i]);
            if(i == CurrentDistance){
                step ++;
                CurrentDistance = NextDistance;
                if(NextDistance >= nums.size()-1) break;
            }
        }
        return step;
    }
};

1005.K次取反后最大化的数组和  

本题简单一些,估计大家不用想着贪心 ,用自己直觉也会有思路。 

关键有二:一个是sort的用法,怎么去定义排序规则;一个是当k没有用完则反转最小的数剩余次数,如果是奇数就是反转一下,如果是偶数就是保持不变。

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
static bool cmp(int a , int b){
    return abs(a) > abs(b);//降序
}
public:
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        int res = 0;
        sort(nums.begin(), nums.end(), cmp);
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] < 0 && k > 0){//将最大的负数取反
                nums[i] = -nums[i];
                k--;
            }
        }
        if( k>0 && k%2==1) nums[nums.size()-1] *= -1;//将最小的值反转一下
        for(int n:nums) res += n;
        return res;
    }
};

134. 加油站 

本题有点难度,不太好想,推荐大家熟悉一下方法二 

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int size = gas.size();
        vector<int> pure(size);
        int Cursum = 0;
        int CursumMin = INT_MAX;
        int index;
        for(int i = 0; i < size; i++){
            pure[i] = gas[i] - cost[i];
            Cursum = Cursum + pure[i];
            cout << Cursum << endl;
            if(Cursum <= CursumMin){
                index = i + 1;//默认标号是0时 cursum = 0; 此后计算时index是标号的后一个数
                CursumMin = Cursum;
            }
        }
        if(Cursum >= 0)  return index;//此时Cursum就是总和
        else return -1;
    }
};

135. 分发糖果 

本题涉及到一个思想,就是想处理好一边再处理另一边,不要两边想着一起兼顾,后面还会有题目用到这个思路 

代码随想录代码随想录

class Solution {
public:
    int candy(vector<int>& ratings) {
        int res = 0;
        vector<int> candy(ratings.size(), 1);//每个child至少一个糖果
        for(int i = 1; i < ratings.size(); i++){
            if(ratings[i] > ratings[i - 1]){
                candy[i] = candy[i - 1] + 1;
            }
        }
        for(int i = ratings.size() - 2; i >= 0; i--){
            if(ratings[i] > ratings[i + 1]){
                candy[i] = candy[i + 1] + 1;
            }
        }
        for(int i = 0; i < ratings.size(); i++){
            res = res + candy[i];
        }
        return res;
    }
};

860.柠檬水找零 

本题看上好像挺难,其实挺简单的。关键是当收到20元时,优先用一张10元和一张5元找开,没有的话再用三张5元找开。

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int five = 0, ten = 0, tewlve = 0;
        for(int bill:bills){
            if(bill == 5){
                five ++;
            }
            if(bill == 10){
                if(five > 0){
                    five --;
                    ten ++;
                }else return false;
            }
            if(bill == 20){
                if(five > 0 && ten > 0){
                    five --;
                    ten --;
                    // tewlve ++;
                }
                else if(five >= 3){
                    five -= 3;
                    // tewlve ++;
                }else return false;
            }
        }
        return true;
    }
};

406.根据身高重建队列 

本题有点难度,和分发糖果类似,不要两头兼顾,处理好一边再处理另一边。 

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
private:
    static bool cmp(vector<int>& a, vector<int>& b){
        return a[0] > b[0];
    }
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(),people.end(),cmp);//按照第一个元素排序
        vector<vector<int>> que;
        for(int i = 0; i < people.size(); i++){
            int position = people[i][1];
            que.insert(que.begin()+position,people[i]);//ATTENTION
        }
        return que;
    }
};

重叠区间

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

本题是一道 重叠区间的题目,好好做一做,因为明天三道题目,都是 重叠区间。 

代码随想录

力扣题目链接

class Solution {
private:
    static bool cmp(vector<int>& a, vector<int>& b){//ATTENTION: vector<int>&
        return a[0] < b[0];
    }
public:
    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.size() == 0) return 0;
        int res = 1;//poins不为空,至少需要一支箭
        sort(points.begin(),points.end(),cmp);//按第一个元素从小到大排序
        for(int i = 1; i < points.size(); i++){
            if(points[i-1][1] < points[i][0]) res++;//需要一支箭
            else{
                points[i][1] = min(points[i][1], points[i-1][1]);//更新最小右边界(这里如果新开一个变量会不太方便)
            }
        } 
        return res;

    }
};

二刷写的

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

435. 无重叠区间 

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

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

763.划分字母区间 

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    vector<int> partitionLabels(string s) {
        int hash[27]={0};
        vector<int> res;
        for(int i = 0; i < s.size(); i++){
            hash[s[i] - 'a'] = i;//覆盖,最终保存最远距离
        }
        // cout << hash[0] <<endl;
        int left = 0;
        int right= 0;
        for(int i = 0; i < s.size(); i++){
            right = max(right, hash[s[i] - 'a']);
            if(right == i){
                res.push_back(right - left + 1);
                left = i + 1;
            }
        }
        return res;
    }
};

56. 合并区间  

本题相对来说就比较难了。

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> res;
         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];});
        res.push_back(intervals[0]);
        for(int i = 0; i < intervals.size(); i++){
            if(res.back()[1] >= intervals[i][0]){
                res.back()[1] = max(res.back()[1], intervals[i][1]);
            }else{
                res.push_back(intervals[i]);
            }
        }
        return res;
    }
};

我的二刷:

我用了个slow指针控制新向量的移动速度,方便索引vec[slow][1],代码随想录里面用的vec.back()[1]来索引这个值,也成。

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

我的一刷:(可通过)

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if(intervals.size() < 2) return intervals;
        sort(intervals.begin(), intervals.end(),cmp);
        vector<vector<int>> outElement;
        int element2 = intervals[0][1];
        int element1 = intervals[0][0];
        for(int i = 1; i < intervals.size(); i++){
            cout << element2 << '*' << intervals[i][0] <<endl;
            if(element2 >= intervals[i][0]){
                element2 = max(element2, intervals[i][1]);
            }else{
                outElement.push_back({element1, element2});
                element1 = intervals[i][0];
                element2 = intervals[i][1];
            }
        }
        outElement.push_back({element1,element2});
        return outElement;

    }
    static bool cmp(vector<int> a, vector<int> b){
        return a[0] < b[0];
    }
};

738.单调递增的数字 

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

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

968.监控二叉树 (可以跳过)

本题是贪心和二叉树的一个结合,比较难,一刷大家就跳过吧。 

代码随想录

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

总结 

可以看看贪心算法的总结,贪心本来就没啥规律,能写出个总结篇真的不容易了。 

代码随想录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值