细谈贪心算法

一.贪心算法解题步骤:

1.将问题分解为若⼲个⼦问题
2.找出适合的贪⼼策略
3.求解每⼀个子问题的最优解
4.将局部最优解堆叠成全局最优解
二.例题:
(1)分发饼干: https://leetcode-cn.com/problems/assign-cookies/
局部最优:先用最小的饼干喂饱胃口小的孩子,充分利用每一个饼干的尺寸;全局最优:喂饱
尽可能多的孩子。
//假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,
//每个孩子最多只能给一块饼干。

//对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;
//并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,
//这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

public int findContentChildren(int[] g, int[] s) {
        //用小饼干先满足小胃口的孩子 直到遍历到最后一块饼干
        int index = 0;
        Arrays.sort(g);
        Arrays.sort(s);
        for(int i=0;i<s.length;i++){
            if(index < g.length && g[index] <= s[i]){
                index++;
            }
        }
        return index;
    }
(2)摆动序列 https://leetcode-cn.com/problems/wiggle-subsequence/
[1,17,5,10,13,15,10,5,16,8]
局部最优:删除上升或下降坡度中间的值,就得到了两个局部峰值;全局最优:保留整个序列中最多的局部峰值,就是最长序列。
//如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。
//第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
public int wiggleMaxLength(int[] nums) {
        if(nums.length <= 1){
            return nums.length;
        }
        int curdiff = 0,prediff = 0,result = 1;
        for(int i=0;i<nums.length-1;i++){
            curdiff = nums[i+1]-nums[i];
            if(prediff>=0 && curdiff<0 || prediff<=0 && curdiff>0){
                result++;
                prediff = curdiff;
            }
        }
        return result;
    }
(3)最大子序和  https://leetcode-cn.com/problems/maximum-subarray/
局部最优:前一个连续和与当前值的和小于当前值,说明当前连续和不合适了,应该立即放弃,重新更新连续和计算起点。
全局最优:遍历数组结束后,选取最大连续和。
//给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组
//(子数组最少包含一个元素),返回其最大和。
public int maxSubArray(int[] nums) {
        int sum = 0;
        int result = -10000;
        for(int i=0;i<nums.length;i++){
            if(sum+nums[i]>=nums[i]){
                sum+=nums[i];
            }else{
                sum = nums[i];
            }
            if(result < sum){
                result = sum;
            }
        }
        return result;
    }
(4)买卖股票的最佳时机Ⅱ  https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/
局部最优:当前值为正。
全局最优:所有局部最优的和。
//给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

//在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。
//你也可以先购买,然后在 同一天 出售。

//返回 你能获得的 最大 利润 。
public int maxProfit(int[] prices) {
        //贪心
        int result = 0;
        for(int i=0;i<prices.length-1;i++){
            if(prices[i+1]-prices[i]>=0){
                result+=prices[i+1]-prices[i];
            }
        }
        return result;
    }
(5)跳跃游戏Ⅱ   https://leetcode-cn.com/problems/jump-game-ii/
局部最优:以最小的步数覆盖最大的范围。
全局最优:覆盖最终范围。
//给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。

//每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。
//换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

public int jump(int[] nums) {
        int curDistants = 0,nextDistants = 0,result = 0;
        for(int i=0;i<nums.length-1;i++){
            nextDistants = Math.max(i+nums[i],nextDistants);
            if(i == curDistants){
                curDistants = nextDistants;
                result++;
            }
        }
        return result;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值