贪心算法总结


根据卡尔的说法,贪心算法没有所谓的套路框架,只有常识。一般来说,贪心算法只要能把测试案例跑通就可以,不需要去证明,贪心不可以,那么就是可以切换到使用动态规划了。

455. 分发饼干

这是一个简单的贪心思想题目,每次满足胃口值最小的孩子,于此同时,我还是运用了双指针的思想。

class Solution {
    public int findContentChildren(int[] g, int[] s) {
        /**
        分析:
        简单的贪心思想,小饼干给小胃口值的孩子
         */
         int count = 0;
         // 对两个数组排好序
         Arrays.sort(g);
         Arrays.sort(s);
         // 定义双指针,特定情况下i指针移动,j指针一直移动
         for(int i = 0,j = 0; i < g.length && j < s.length;){
              if(s[j] >= g[i]){
                  // 胃口值得到,满足
                  i++;
                  count++;
              }
              // 切换到下一个饼干
              j++;
         }
         return count;

    }
}

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

做完这道题很担心会超时,但是没有超时,很危险的解法,有点像暴力法

class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        /**
        分析:
        每次选择一个数的时候,都是选取当前数组中的最小值(可以重复选取),上一轮的操作结果会影响下一轮的选取
         */
         // 先排好序
         Arrays.sort(nums);
         int count = 0;
        while(count < k){
            nums[0] = -nums[0];
            // 重新排序
            Arrays.sort(nums);
            count++;
        }
        int sum = 0;
        for(int x:nums){
            sum += x;
        }
        return sum;
    }
}

860. 柠檬水找零

这是一个生活常识问题应用在leetcode的贪心算法中

class Solution {
    public boolean lemonadeChange(int[] bills) {
        /**
        分析:
        常识知道:5元是万金油的,可以用来支付10元账单也可以用来支付20元账单,所以当遇到20元账单的时候,应该优先消费10元+5元的组合,贪心的保留5元
         */
         int len = bills.length;
         int five = 0, ten = 0;
         for(int i = 0; i < len; i++){
             // 遇到5元,存起来
             if(bills[i] == 5){
                 five++;
             }else if(bills[i] == 10 ){
                 // 遇到10元,消费5元
                if(five <= 0){
                    return false;
                }
                five--;
                ten++;
             }else if(five > 0 && ten > 0){
                 // 剩下的就是20元的了,优先消费10元+5元组合
                 five--;
                 ten--;
             }else {
                 // 最后消费3张5元的
                 if(five < 3){
                     return false;
                 }
                 five -= 3;
             }
             
         }
         return true;

    }
}

376. 摆动序列

每次都贪心的去寻找峰值???有点像是语文题,其中用了一个技巧就是加入前导数字,解决了前后坡度高度差问题。其实只要想明白了,前后高度差必须要有三个数才可以计算,自然而然就会想到使用前导数字

class Solution {
    public int wiggleMaxLength(int[] nums) {
        /**
        分析:
        刚开始看到这道题是很慌的,题目实际上就是要求局部峰值的个数。因为题目谈到了子序列的话题,所以很容易就想到了能不能去删除原始数组的一些数,然后求数组的长度。进入这个误区就很难了额,数组的删除???这个操作麻烦啊,所以还是切换思路,能不能只计算峰值个数,不要去做删除操作。

         */
         // 只有一个数字 那必然是摆动的
         if(nums.length == 1){
             return 1;
         }
         // 若数字是大于等于2个,如何计算峰值???
         // 首先要想到,判断峰值是通过前后的高度差来计算的,也就是说,至少得有3个数!!!
         // 前面的高度差和  后面的高度差必须正负号相反,否则就是单调的了
         // 那么怎么处理两个数的情况? [2,2] 和[2,5]? 默认给一个前导数2 [2,2,2] 和[2,2,5]
         
         // 初始化
         int preDiff = 0;
         int curDiff = 0;
         // 初始化的个数为1
         int count = 1;
         for(int i = 1; i < nums.length; i++){
             // 当前高度差
             curDiff = nums[i] - nums[i-1];
             // 这里的preDiff取等号0 是为了判断 初始化条件的
             // 如果curDiff=0 是进入不了if语句的
             if(curDiff > 0 && preDiff <= 0 || curDiff < 0 && preDiff >= 0){
                 // 计数
                 count++;
                 // 更新
                 preDiff = curDiff;
             }
         }
         return count;

    }
}

55. 跳跃游戏

class Solution {
    public boolean canJump(int[] nums) {
        /**
        分析:
        使用贪心策略解题,每次都贪婪的选择下一个可能达到的最大目标.最远能到达某个位置,就一定能到达它前面的任何位置。
         */
         // 记录最大位置下标  初始化为0
         int maxPos = 0;
         for(int i = 0; i < nums.length; i++){
             // 遍历数组
             // 发现 i 超过了maxPos,说明遇到0了,已经跳不出去了
             if(i > maxPos) return false;
             // 更新最大下标
             maxPos = Math.max(maxPos,i+nums[i]);
         }
         // 遍历结束 返回true
         return true;

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值