8. 贪心算法(Greedy)

1 实现与特性

  1. 每一步中都采取当前状态下最好或最优的解法,从而使全局解法最优
  2. 与动态规划的不同是,他对于每个子问题的解决方案都会做出选择,不能回退。而动态规划则会保存之前的运算结果 ,并根据以前的结果对当前进行选择,能够退回
  3. 所有子方案最优不一定能全局最优
  4. 对于工程和生活中的问题贪心算法一般不能得到我们想得到的答案

1.1 什么情况能用贪心算法

  1. 问题能够分成最优子问题来解决,子问题的最优解能递推到最终问题的最优解,也就是最优子结构问题
  2. 可以解决最优化的问题,如求图中最小生成树,求哈夫曼编码等
  3. 因为贪心算法的高效性 可作为辅助算法或者直接解决一些要求结果不特别精确的问题

2. 算法题解

1)零钱兑换

2)分发饼干

  • 贪心算法:
  • 先对两个数组排序,双指针,饼干满足胃口的+1,不能满足胃口的继续向后找
  • 满足第一个的胃口后移动指正继续找下一个
/*
 * @lc app=leetcode.cn id=455 lang=java
 *
 * [455] 分发饼干

 */

// @lc code=start
class Solution {
    public int findContentChildren(int[] g, int[] s) {
        if (g == null || s == null) return 0;
        Arrays.sort(g);
        Arrays.sort(s);
        int gi = 0;
        int si = 0;
        // 直到饼干分完或者小朋友都满足了结束
        while (gi < g.length && si < s.length) {
            // 如果小盆友的胃口小于等于饼干分量,则下一个小朋友分
            if (g[gi] <= s[si]) gi++;
            si++;
        }
        return gi;
    }
}
// @lc code=end

3)买卖股票的最佳时机 II

  • 贪心算法的解法是:有利润就买,没有利润就不买
  • 只要明天的售价大于今天的售价,那么就买今天的明天再售出
  • 得到每次的利润加起来就是最大利润
  • 可以看做是一个折线图,最低点到最高点的距离等同于每一步上升的距离(有利润)
import java.time.temporal.Temporal;

/*
 * @lc app=leetcode.cn id=121 lang=java
 *
 * [121] 买卖股票的最佳时机

 */

// @lc code=start
class Solution {
    public int maxProfit(int[] prices) {
        int profit = 0;
        for (int i = 0; i < prices.length; i++) {
            int tmp = prices[i] - prices[i - 1];
            if (tmp > 0) profit += tmp;
        }
        return profit;
    }
}
// @lc code=end


4)跳跃游戏

贪心算法思路,逆推,从末位元素开始遍历数组
判断当前位置(下标)+当前步数是否能 >= 终点位置
满足条件说明能到达终点,那就将当前位置设为终点,如果到下标为0的时候也能到达终点
输入: [2,3,1,1,4]

  • 3 + 1 = 4 能到终点,将下标3设为终点
  • 2 + 1 = 3 能到终点,将下标2设为终点
  • 直到遍历完数组,下标0将设为终点,说明此数组满足条件

输入: [3,2,1,0,4]

  • 3 + 0 < 4 不能到终点
  • 2 + 1 < 4
  • 1 + 2 < 4
  • 0 + 3 < 4
  • 始终到不了终点,所以此时终点值不为0,不满足条件
/*
 * @lc app=leetcode.cn id=55 lang=java
 *
 * [55] 跳跃游戏

 */

// @lc code=start
class Solution {
    public boolean canJump(int[] nums) {
        int lastPos = nums.length - 1; // 终点位置下标
        for (int i = nums.length - 1; i >= 0 ; i--) {
            // 
            if (i + nums[i] >= lastPos) lastPos = i; // 如果当前位置能到终点,就把当前位置设为终点
        }
        return lastPos == 0;
    }
}
// @lc code=end


发布了90 篇原创文章 · 获赞 4 · 访问量 1430

猜你喜欢

转载自blog.csdn.net/weixin_44145258/article/details/103753346