LeetCode Hot 100——贪心算法

121. 买卖股票的最佳时机

把每天价格当成一条曲线。你想在某天卖出时赚钱最多,就等价于:

对每一天 i 作为"卖出日",找它之前出现过的最低价格作为"买入价"。

所以只要一路扫过去,同时维护:

  • 到今天为止的最低价 minPrice
  • 到今天为止的最大利润 maxProfit

当你看到今天价格 price

  • 如果今天卖:利润 = price - minPrice
  • 更新最大利润
  • 顺便更新 minPrice = min(minPrice, price)
java 复制代码
class Solution {
    public int maxProfit(int[] prices) {
        int minPrice = Integer.MAX_VALUE;
        int maxProfit = 0;
        for(int p : prices) {
            if(p < minPrice) {
                minPrice = p;
            }
            maxProfit = Math.max(maxProfit, p - minPrice);
        }
        return maxProfit;
    }
}

55. 跳跃游戏

贪心本质:维护"最远可达位置" far

从左到右扫:

  • far 表示:在当前已经能到达的范围内,通过某个点再跳一步,最远能到哪
  • 如果扫到某个位置 i 时发现 i > far:说明 这个位置根本到不了,后面更不可能到,直接 false
  • 否则更新:far = max(far, i + nums[i])
  • 最后如果 far >= n-1 就能到终点
java 复制代码
class Solution {
    public boolean canJump(int[] nums) {
        int far = 0;
        for(int i = 0;i < nums.length;++i) {
            if(i > far) {
                return false;
            }
            far = Math.max(far, i + nums[i]);
            if(far >= nums.length - 1) return true;
        }
        return true;
    }
}

45. 跳跃游戏 II

核心思路:两段边界 + 一次扫描

维护三个量:

  • end:当前这一跳能覆盖到的最右边界(这一层的边界)
  • far:在扫描当前层 [0..end] 的过程中,能拓展到的下一层最远位置
  • steps:跳跃次数

扫描 i 从 0 到 n-2(最后一个点不需要再跳):

  1. 更新下一层最远:far = max(far, i + nums[i])
  2. 如果 i == end,说明当前层扫描完了,必须"跳一次"进入下一层:
  3. steps++
  4. end = far(把当前层边界推进到下一层最远)

为什么对?

因为你在当前这一跳能到的所有位置里,选一个点作为落脚点,你希望下一跳覆盖最远;扫描这一层时取到的最大 i+nums[i] 就是最优的下一层边界。

java 复制代码
class Solution {
    public int jump(int[] nums) {
        int n = nums.length;
        int end = 0; // 当前跳的边界
        int far = 0; // 下一跳的最远边界
        int steps = 0; // 记录步数
        for(int i = 0;i < n - 1;++i) { // 注意是小于n-1, 因为到终点不用再跳,无需扫描
            far = Math.max(far, i + nums[i]);
            if(i == end) {
                steps++;
                end = far; // 每次跳时吧end更新为上一轮记录的far
            }
        }
        return steps;
    }
}

763. 划分字母区间

核心思路:先记录每个字符最后出现的位置

做两步:

Step A:统计 last[c]

last[c] = 字符 c 在字符串中最后出现的下标。

Step B:从左到右扫,动态扩展当前片段的右边界 end

  • 设当前片段起点 start
  • 扫描到位置 i,字符是 s[i]
  • 更新 end = max(end, last[s[i]])
    意思是:当前片段里出现的所有字符,它们的最后位置都必须被包含进来
  • i == end:说明这段已经"封口"了(片段里所有字符的最后一次出现都在片段内),可以切一刀:
    • 片段长度 end - start + 1
    • start = i + 1 开启下一段

这是贪心:能尽早切就尽早切,因为一旦满足条件(i==end),再往右只会让片段变长,不会让片段数量更多/更优。

java 复制代码
class Solution {
    public List<Integer> partitionLabels(String s) {
        int[] last = new int[26];
        int n = s.length();
        for(int i = 0;i < n;++i) {
            last[s.charAt(i) - 'a'] = i;
        }
        int start = 0, end = 0;
        List<Integer> res = new ArrayList<>();
        for(int i = 0;i < n;++i) {
            end = Math.max(end, last[s.charAt(i) - 'a']);
            if(i == end) {
                res.add(end - start + 1);
                start = i + 1;
            }
        }
        return res;
    }
}
相关推荐
sel_913 分钟前
【强化学习】Hands-on Modern RL项目实践|OPD 算法完整解析
人工智能·深度学习·算法·机器学习·语言模型
Navigator_Z1 小时前
LeetCode //C - 1209. Remove All Adjacent Duplicates in String II
c语言·算法·leetcode
落魄大学生之流水线上谋生计1 小时前
Java锁全面指南:从基础概念到企业级应用
java·开发语言
爱学习的小白柏2 小时前
【AI问数技术】多Agent协同架构:查询规划/SQL生成/洞察分析/报告生成
java·网络·人工智能·windows·sql·架构·llama
码匠许师傅2 小时前
【C++ 面试真题】30. 聊聊 C++ 的互斥锁与读写锁
java·c++·面试
沙盘客2 小时前
AFSIM 示例解读(03)· 六自由度飞行仿真 six_dof(下):机场运作与弹道导弹投送
java·javascript·经验分享
ShineWinsu3 小时前
对于 C++:C++14中从变量模板、泛型 Lambda 到并发与字面量的解析
c++·算法
CHANCE V3 小时前
集合排序和流排序
java
土司大王3 小时前
LeetCode hot100——合并两个有序链表
算法·leetcode·链表