20210322 :贪心思想力扣典型题目合集

贪心思想力扣典型题目合集

写在前面

  1. 贪心的思想很多时候在于想到那个贪心的点上,而对徒手书写某些代码结构的能力并不做要求,个人认为需要的是你敏锐的意识到这个贪心的点在哪里。
  2. 列举出这几道典型题目作为回顾与复习。

题目列表

    1. 分发饼干

在这里插入图片描述
2. 376. 摆动序列
在这里插入图片描述
3. 402. 移掉K位数字
在这里插入图片描述
4. 55. 跳跃游戏
在这里插入图片描述
5. 45. 跳跃游戏 II
在这里插入图片描述
6. 452. 用最少数量的箭引爆气球
在这里插入图片描述
不直观,给个更直观的图:在这里插入图片描述

思路分析

  1. 分发饼干:贪心点在于:尽可能小的饼干满足尽可能多的孩子。
  2. 摆动序列:贪心点在于:只计算摆动的长度,这里涉及一个类似数字电路里状态机,准确来讲是米粒型状态机的写法,在此类题目中很有用。建议掌握
  3. 移掉K位数字:贪心点在于:从高位向低位去,去的时候对比大小,去大的符合预期。
  4. 跳跃游戏:贪心点在于:如何不浪费跳跃距离,那么我们可以考虑从终点倒推起点,最后看起点是否索引为0即可。
  5. .跳跃游戏 II:贪心点在于:与上题相同,依旧在于不浪费跳跃距离,那么我们考虑当前跳跃是否为必要跳跃,注释的比较详细,见代码。
  6. 用最少数量的箭引爆气球:贪心点在于:是否需要增加弓箭手,单个弓箭手的最优射击范围的维护。

代码实现

    1. 分发饼干
class Solution {
    
    
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
    
    
        // 排序操作
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());

        // 遍历
        int child = 0;
        int candy = 0;
        while (child < g.size() && candy < s.size()) {
    
    
            if (g[child] <= s[candy] ) {
    
    
                child++;
            }
            candy++;
        }
        return child;
    }
};
    1. 摆动序列
class Solution {
    
    
public:
    int wiggleMaxLength(vector<int>& nums) {
    
    
        int len = nums.size();
        if (len < 2) {
    
    
            return len;
        }
        static const int BEGIN = 0;
        static const int UP = 1;
        static const int DOWN = 2;
        int STATE = BEGIN;
        int max_length = 1;
        for (int i = 1; i < len; ++i) {
    
    
            switch (STATE) {
    
    
                case BEGIN:
                    if (nums[i - 1] < nums[i]) {
    
    
                        STATE = UP;
                        max_length++;
                    } else if (nums[i - 1] > nums[i]) {
    
    
                        STATE = DOWN;
                        max_length++;
                    }
                    break;
                case UP:
                    if (nums[i - 1] > nums[i]) {
    
    
                        STATE = DOWN;
                        max_length++;
                    }
                    break;
                case DOWN:
                    if (nums[i - 1] < nums[i]) {
    
    
                        STATE = UP;
                        max_length++;
                    }
                    break;
            }
        }
        return max_length;
    }
};
    1. 移掉K位数字
class Solution {
    
    
public:
    string removeKdigits(string num, int k) {
    
    
        vector<int> S;
        string result = "";
        for (int i = 0; i < num.size(); ++i) {
    
    
            int number = num[i] - '0';
            while ( (S.size() != 0) &&  (number < S[S.size() - 1]) && (k > 0) ) {
    
    
                S.pop_back();
                k--;
            }
            if (number != 0 || S.size() != 0) {
    
    
                S.push_back(number);
            }
        }

        while (S.size() != 0 && k > 0) {
    
    
            S.pop_back();
            k--;
        }
        for (int i = 0;i < S.size(); ++i) {
    
    
            result.append(1,('0'+S[i]) );
        }
        if (result == "") {
    
    
            result = "0";
        }
        return result;
    }
};
    1. 跳跃游戏
class Solution {
    
    
public:
    bool canJump(vector<int>& nums) {
    
    
        int lastPos = nums.size() - 1;
		for (int i = nums.size() - 2; i >= 0; i--) {
    
    
			if (i + nums[i] >= lastPos) {
    
    
				lastPos = i;
			}
		}
		return lastPos == 0;
    }
};
    1. 跳跃游戏 II
class Solution {
    
    
public:
    int jump(vector<int>& nums) {
    
    
        // 特况处理
        if (nums.size() <= 1) {
    
    
            return 0;
        }

        // 遍历,使用两个变量存储当前可以到达的最大距离和是否需要必要跳跃
        int cur_max = nums[0];
        int pre_max = nums[0];
        int res = 1;
        for (int i = 1; i < nums.size(); ++i) {
    
    
            // 更新cur_max:之前需要依次必要跳跃,res增加1,并同步更新当前最远距离
            if (i > cur_max) {
    
    
                res++;
                cur_max = pre_max;
            }
            
            // 更新pre_max以判断其是否需要用于更新当前最大距离
            if (nums[i] + i > pre_max)  {
    
    
                pre_max = nums[i] + i;
            }
        }
        return res;
    }
};
    1. 用最少数量的箭引爆气球
bool cmp(const vector<int>& a,const vector<int>& b){
    
    
    return a[1] < b[1];
}

class Solution {
    
    
public:
    int findMinArrowShots(vector<vector<int>>& points) {
    
    
        if (points.size() == 0) {
    
    
            return 0;
        }
        // 根据左端点进行排序
        sort(points.begin(),points.end(),cmp);
        // 维护当前弓箭手最优射击区间
        int shoot_num = 1;
        int shoot_begin = points[0][0];
        int shoot_end = points[0][1];

        for (int i = 1; i < points.size(); ++i) {
    
    
            if (points[i][0] <= shoot_end) {
    
    
                shoot_begin = points[i][0];
                if (shoot_end > points[i][1]) {
    
    
                    shoot_end = points[i][1];
                }
            } else {
    
    
                shoot_num++;
                shoot_begin = points[i][0];
                shoot_end = points[i][1];
            }
        }
        return shoot_num;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_36828395/article/details/115103178