前言
解决问题的一般步骤都是,问题本质发现,component解题,发现缺点进行改进。如跳跃游戏问题,问题本质发现-0-沼泽问题 -》DFS-component解题 -》贪心-component改进。
一、跳跃游戏
二、沼泽问题
1、DFS模拟
//跳跃游戏
public class CanJump {
//核心是进到0位就是沼泽,无法再行走。
//方法是越过0-沼泽
//M1:暴搜
public boolean canJump(int[] nums) {
return dfs(nums, 0, nums.length);
}
private boolean dfs(int[] nums, int cur, int len) {
//到达了最后一个及以后,表示跳跃成功。
if (cur >= len - 1) return true;
int size = nums[cur];
if (nums[cur] == 0) return false;//到达了沼泽,表示该跳跃方式行不通。
//暴力跳跃
for (int k = size; k > 0; k--) {
boolean flag = dfs(nums, cur + size, len);
if (flag) return true;//一旦成功,则表示成功。
}
return false;//所有方案都不成功,则表示失败。
}
}
2、贪心
//M1-爆搜-缺点:时间复杂度较高。
//idea:空间换时间,记住一些有用的东西。
//M2:0-沼泽处是关键地带,如果遇到0-沼泽,要看之前能跳跃到最远的距离是否能越过当前0-沼泽。
class CanJump2 {
public boolean canJump(int[] nums) {
int max = 0;//最远距离记录
//从左到右遍历nums,并更新max distance
int len = nums.length;
for (int i = 0; i < len - 1; i++) {
//进入沼泽,且该沼泽无法越过。
if (0 == nums[i] && max <= i)
return false;//无法越过的沼泽地
//可以越过沼泽 || 没有遇到沼泽,进行统一处理,并更新max distance
int dis = nums[i] + i;
if (max < dis) {
max = dis;
if (max >= len - 1) return true;//有新的max distance,看是否能直接到达终点。
}
}
return true;//缓慢的到达了终点。
}
//总结
//1-不要死靠记忆,要memory + current thinking
//2-看似简单的逻辑(多细节简单题),实践起来却考察逻辑连贯性和多逻辑整合能力。所以学完要独立实践,训练coding+thinking能力。
//3-报持严谨的逻辑,那么写出来表达出来的东西将传递你的严谨性。
//4-为什么每次做困难题能做出来,但是要做很久?很久的原因?因为了解信息不全,信息整理能力差,拆解信息能力弱。这样就浪费了时间,而且训练效果也差。
}
总结
1)不要死靠记忆,要memory + current thinking
2)看似简单的逻辑(多细节简单题),实践起来却考察逻辑连贯性和多逻辑整合能力。所以学完要独立实践,训练coding+thinking能力。
3)报持严谨的逻辑,那么写出来表达出来的东西将传递你的严谨性。
4)为什么每次做困难题能做出来,但是要做很久?很久的原因?因为了解信息不全,信息整理能力差,拆解信息能力弱。这样就浪费了时间,而且训练效果也差。
参考文献
[1] LeetCode 跳跃游戏