Hot100 贪心算法
如果非要说这些题的共性,也许就是:在边界内不断寻找最优解
121. 买卖股票的最佳时机 - 力扣(LeetCode)
总结一下思路就是:如果第i天卖出股票,则最大利润为(该天的股价-前面天数中最小的股价),然后与已知的最大利润比较,如果大于则更新当前最大利润的值。
分享|股票问题系列通解(转载翻译) - 力扣(LeetCode)
53. 最大子数组和 - 力扣(LeetCode)
55. 跳跃游戏 - 力扣(LeetCode)
使用贪心算法,维护一个变量 maxReach
,表示当前能够到达的最远位置。遍历数组时,更新 maxReach
,如果在某个位置无法再前进,则直接返回 false
。如果能够到达或超过最后一个位置,则返回 true
。
class Solution {
public boolean canJump(int[] nums) {
//每个nums[i]维护的是最大跳跃长度 你当然也可以只跳1,2步
int maxreach=0;
for(int i=0;i<nums.length;i++)
{
if(maxreach<i)
{
//跳不到这里
return false;
}
if(maxreach>=nums.length-1)
{
//已经可以跳跃的最长长度大于数组长度了
return true;
}
maxreach=Math.max(maxreach,i+nums[i]);
}
//一直到最后也没到末尾
return false;
}
}
45. 跳跃游戏 II - 力扣(LeetCode)
核心思路
算法的核心是贪心思想:每次跳跃时,选择一个能够到达的最远位置,这样可以尽量减少跳跃次数。当然了,每次都跳到最远的也不一定能得到好的结果,所以我们就额外在每次的边界内探索一下如果不跳最远的话是不是有更好的结果
注意:
-
i < nums.length - 1
:-
确保循环在到达最后一个位置之前结束。
-
如果在循环结束时,
border
已经大于或等于nums.length - 1
,说明可以到达终点。
-
public class Solution {
public int jump(int[] nums) {
int jumps = 0; // 跳跃次数
int border = 0; // 记录当前能跳跃到的位置的边界下标
int farthest = 0; // 记录在边界范围内,能跳跃的最远位置的下标
for (int i = 0; i < nums.lengh - 1; i++) {
// 继续往下遍历,统计边界范围内,哪一格能跳得更远,每走一步就更新一次能跳跃的最远位置下标
farthest = Math.max(farthest, i + nums[i]);
if (i == border) { // 如果到达当前跳跃的最远位置
jumps += 1; // 增加跳跃次数
border = farthest; // 更新当前跳跃的边界
}
}
return jumps; // 返回最小跳跃次数
}
}
非要加的花
public class Solution {
public int jump(int[] nums) {
int border=0;
int jump=0;
int maxreach=0;
for(int i=0;i<nums.length;i++)
{
//每一个节点都要看看最远能到哪
maxreach=Math.max(maxreach,nums[i]+i);
if(border==nums.length-1) return jump;
if(i==border)
{
// 该跳跃了,不管接下来走几步都算是一次跳跃
jump++;
border=maxreach;//更新当前点出发的边界
}
}
return jump;
}
}
763. 划分字母区间 - 力扣(LeetCode)
其实还是有点稀里糊涂的 ,没有办法找到共性。
class Solution {
public List<Integer> partitionLabels(String s) {
int end=-1;
int start=0;
List<Integer> result = new ArrayList<>();
// key 字符; value 出现一系列下标集合
Map<Character, Integer> map = new HashMap<>();
// 第一次遍历:记录每个字符的最远位置
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
map.put(c, i); // 更新字符的最远位置
}
//第二次遍历 用来扫描切割区间
for(int i=0;i<s.length();i++)
{
char c=s.charAt(i);
//更新当前end
end=Math.max(end,map.get(c));
//遍历字符串,如果已扫描部分的所有字符,都只出现在已扫描的范围内,即可做切割。
if(i==end)
{
//当前边界之前所有节点已经被判断过 没有后面出现的更新了end
result.add(end-start+1);
start=end+1;
}
}
return result;
}
}