1 实现与特性
- 每一步中都采取当前状态下最好或最优的解法,从而使全局解法最优
- 与动态规划的不同是,他对于每个子问题的解决方案都会做出选择,不能回退。而动态规划则会保存之前的运算结果 ,并根据以前的结果对当前进行选择,能够退回
- 所有子方案最优不一定能全局最优
- 对于工程和生活中的问题贪心算法一般不能得到我们想得到的答案
1.1 什么情况能用贪心算法
- 问题能够分成最优子问题来解决,子问题的最优解能递推到最终问题的最优解,也就是最优子结构问题
- 可以解决最优化的问题,如求图中最小生成树,求哈夫曼编码等
- 因为贪心算法的高效性 可作为辅助算法或者直接解决一些要求结果不特别精确的问题
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