贪心算法part1

贪心算法part1

理论基础

什么是贪心?

贪心的本质是选择每一阶段的最优解,从而达到全局最优

举例:有一堆钞票,可以拿走十张,如何达到最大金额?每次拿走最大的钞票

什么时候用贪心?

贪心算法没有固定套路,一般数学证明有以下两种方法

  • 数学归纳法
  • 反证法

最好用的策略是举反例

贪心有时就是常识性的推导,所以会下意识认为本应该就这么做

贪心一般解题步骤

过于理论化的步骤(理想化,但是做题时不好用)

  • 将问题分解为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优解

做题时只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了

总结

贪心没有套路,用的是常识性推导加上举反例,比较抽象

455. 分发饼干 - 力扣(LeetCode)

局部最优:大饼干满足大胃口 --> 全局最优

代码如下:

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);
        int index = s.length - 1;
        int res = 0;
        for(int i = g.length - 1; i >= 0; i--){ //大饼干满足大胃口,遍历胃口数组
            if(index >= 0 && s[index] >= g[i]){
                index--;
                res++;
            }
        }
        return res;
    }
}

376. 摆动序列 - 力扣(LeetCode)

自己做的,感觉也是贪心

局部最优在于:根据当前的state,更新res,并对下面的state进行更新

class Solution {
    public int wiggleMaxLength(int[] nums) {
        int state = -1;
        int res = 0;
        for(int i = 0; i < nums.length; i++){
            if(state == 0){  //现在应该降序了,也就是nums[i] < nums[i - 1]
                if(nums[i] < nums[i - 1]){
                    res++;
                    state = 1;
                }
            }else if(state == 1){  //现在应该升序了,也就是nums[i] > nums[i - 1]
                if(nums[i] > nums[i - 1]){
                    res++;
                    state = 0;
                }
            }else if(state == -1 && i != 0){
                if(nums[i] > nums[i - 1]){
                    state = 0;
                    res++;
                }else if(nums[i] < nums[i - 1]){
                    state = 1;
                    res++;
                }
            }else if(state == -1 && i == 0){
                res++;
            }
        }
        return res;
    }
}

53. 最大子数组和 - 力扣(LeetCode)

贪心

  • 贪得是哪里:如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方

  • 局部最优:当 连续和 为负数的时候直接放弃,从下一个元素重新计算 连续和 ,因为负数只会拖累后面的总和

  • 全局最优:连续选取最大 连续和

代码如下:

class Solution {
    public int maxSubArray(int[] nums) {
        if(nums.length == 1){
            return nums[0];
        }
        int res = Integer.MIN_VALUE;
        int sum = 0;
        for(int i = 0; i < nums.length; i++){
            sum += nums[i];
            res = Math.max(res, sum);
            if(sum < 0){
                sum = 0;
                continue;
            } 
        }
        return res;
    }
}
posted @ 2025-06-19 15:19  泡芙猪  阅读(42)  评论(0)    收藏  举报