文章目录
- 1、贪心算法
- 2、leetcode1217:玩筹码
- 3、leetcode55:跳跃游戏
1、贪心算法
关于贪心算法中,“每一步都是最好的选择"的理解”。以零钱兑换为例,现在有1分、2分、5分的硬币,现在要凑出11分,且要硬币数量最少。
考虑到要硬币数量最少,因此,每一步应当尽可能取面值大的硬币。第一步拿一个5分的,差6,对第一步来说是最优的。第二步接着取一个5分的,差1,第三步取个1分的。
再看上面这个例子,连续取两个5分后,差1,但现在没有1分的面值。那就回溯,重新取下一个最大值,即3。如此,就得到了5、3、3的组合。
但其实,这样也有坑,比如上面这样,按照贪心,结果是10 + 2 + 2,但最优解是 7 + 7。上面这个例子,重点理解这种思想就好。
2、leetcode1217:玩筹码
第 i 个筹码在 position[i],position = [2,2,2,3,3],就是说,第一个筹码在2号位置,第二个筹码也在2号位置,第三个筹码也在2号位置。移动规则:
- position[i] + 2 或 - 2的cost是0,说明不改变筹码所在位置的奇偶性,成本为0,反之,成本为1
由此,这道题的解法思路:
- 把所有偶数位置上的筹码,一个个都移动到2号位置,成本为0
- 把所有奇数位置上的筹码,一个个都移动到1号位置,成本也为0
- 此时,比较1号和2号位置元素,谁少就把谁移动到另一个上去,成本为数量 * 1
如此,每一步就都是最优的,即贪心。分析到这儿,最终返回的就是:遍历position数组,给定统计偶数和奇数的和,返回最小的和即是题解。 代码实现:
public class P1217 {public int minCostToMoveChips(int[] position) {if (null == position || position.length <= 0) {return 0;}// 偶数数量int even = 0;// 奇数数量int odd = 0;for (int e : position) {if (e % 2 == 0) {even++;} else {odd++;}}return Math.min(even, odd);}
}
刷题魔怔了,分析到统计时,第一反应是用HashMap,然而这就两个key:奇数和偶数,直接定义两个变量累加得了。
3、leetcode55:跳跃游戏
在位置x,可以跳的位置有:x+1、x+2、x+3、……、x+nums[i]
,最远可达到x+nums[i] 。
考虑维护一个最远可达到的位置reachRight
,遍历数组,假设当前遍历到了位置 a,而a又满足在最远可达到的位置reachRight的范围之内,也就是说,我从起点开始,经过若干次跳跃,一定可以达到a,那我就可以在a的基础上,更新最远可达到的位置reachRight为 a + nums[a]
往下遍历,一旦出现最远可达到的位置reachRight > 终点下标,即终止循环,返回true,反之,遍历完也不满足 reachRight > 终点下标,则返回false
核心:最远可达到的位置reachRight
public class P55 {public boolean canJump(int[] nums) {if (null == nums || nums.length <= 0) {return false;}// 终点int end = nums.length - 1;//可达的最右端int reachedRight = 0;// 遍历数组,更新当前可以到达的最远位置for (int i = 0; i < nums.length; i++) {//i满足在最远可达到的位置reachRight的范围之内,也就是说,我从起点开始,经过若干次跳跃,一定可以达到iif (i <= reachedRight) {//在i的基础上,更新最远可达到的位置reachRight为 i + nums[i]reachedRight = Math.max(reachedRight, i + nums[i]);}// 一旦出现最远可达到的位置reachRight > 终点下标,即可达if (reachedRight >= end) {return true;}}// 遍历完也不满足 reachRight > 终点下标,则返回falsereturn false;}
}