大家好呀,今天学习贪心算法和两个经典的关于贪心的OJ跳跃游戏1和2
一,贪心简介
贪心算法可以理解为解决问题时每一次都取从当前来看所采取的最优做法,而通过局部最优达到总体最优的目的
1,贪心简介
贪心策略:解决问题的策略,局部最优->全局最优,步骤大致如下
1,把解决问题的过程分为若干步
2,解决每一步的问题时,都采用当前看来“最有效”的解决方法
3,“希望”得到最优解
2,贪心特点
a,贪心策略的提出
1,贪心策略是没有标准以及模板的
2,可能每一道题贪心策略都是不同的
b,贪心策略的正确性
需要注意的是,不是每一道可以用贪心算法的题都适合用贪心,也就是贪心算法可能导致错误的结果(我们往往需要从数学角度上证明贪心算法正确性)又由于每一道题贪心策略都可能不同,因此需要具体分析,但是无论如何,贪心算法的内核其实很简单,就是局部最优推全局最优
那么下面我们就来看两道关于贪心的经典面试题,跳跃游戏
二,经典面试题
1,跳跃游戏2
题目简介
给你一个数组nums,你需要从初始0位置移动到数组末位置,假设数组下标为i,每次可以移动0到i+nums[i]之间任意位置,这样求一直移动到数组最后一个元素
思路
此题我们可以把用相同步数可以到达的位置做一个遍历,如图,假设给定这样一个测试用例,哪个首先我们在初始位置,第二次跳跃可以到达数组下标1和2的位置,在下一次即可以从数组下标1位置跳跃到数组下表2,3,或者4位置,也可以从数组下标2位置跳到3位置,那么综合来看,从数组下标3到4位置便是第三次跳跃可以达到的,因此这样不断的找下取便可以知道最小次数
思路实现
这种思路其实就是通过遍历来找到每次可以到达的区域区间,而下一次可以到达的最大位置则取决于上一个区域的最大值,因此可以定义两个指针指向标示次数的区间,假设为let和right,那么,我们通过left遍历,right更新每次可以到达的最大位置,在加上计数器,便可以实现目的
代码实现(java)
class Solution {
public int jump(int[] nums) {
int left=0;
int right=0;
int count=0;
while(right<nums.length-1){
int j=left;
for(int i=left;i<=right;i++){
if(nums[i]+i>nums[j]+j){
j=i;
}
}
left=right+1;
right=nums[j]+j;
count++;
}
return count;
}
}
易错提示
需要注意的是,我们在写nums[i]+i>nums[j]+j时很容易写成nums[i]>nums[j](我第一次就写错了)需要注意的是在当前数组下表可以移动到的最大位置进行比较时,不仅要考虑数组里的数字,也需要考虑当前数组下标的位置
2,跳跃游戏1
跳跃游戏1与2很类似,只需改动少部分代码,思路是一样的,如果可以到的最大位置有最后一个位置则可以到,否则不能
代码
class Solution {
public boolean canJump(int[] nums) {
int left = 0;
int right = 0;
while (left<=right) {
int j = left;
for (int i = left; i <= right; i++) {
if (nums[i] + i > nums[j] + j) {
j = i;
}
if (nums[j]+j>=nums.length-1) {
return true;
}
}
left = right + 1;
right = nums[j] + j;
}
return false;
}
}
本期博客就到这里,感谢大家支持