力扣hot100—系列4-贪心算法

贪心算法(Greedy Algorithm)的核心思想是:在对问题求解时,每一步都选择当前看起来最好的选择,从而希望最终结果是全局最优的。

贪心算法不需要考虑整体最优,它只关心"眼前"的利益。对于某些特定问题,这种局部最优的选择确实能导致全局最优解。


1. LeetCode 121. 买卖股票的最佳时机 (简单)

题目大意:

给一个数组 prices,其中 prices[i] 表示第 i 天股票的价格。你只能选择某一天买入,并在未来的某一天卖出。求你能获得的最大利润。

思路:

要想赚钱,核心就是:在最低点买入,在最高点(且在买入之后)卖出。

  • 遍历一遍数组。
  • 贪心策略: 记录下到目前为止遇到的"最低价格"。
  • 每一天都假设我今天卖出,利润 = 今天价格 - 之前的最低价格。
  • 不断更新这个利润的最大值。

代码实现 (Python):

python 复制代码
def maxProfit(prices):
    min_price = float('inf')  # 记录遇到的最低价格,初始化为无穷大
    max_profit = 0            # 记录最大利润
    
    for price in prices:
        # 贪心:总是保留之前看到的最小值
        if price < min_price:
            min_price = price
        # 贪心:如果今天卖出赚得更多,就更新最大利润
        elif price - min_price > max_profit:
            max_profit = price - min_price
            
    return max_profit

2. LeetCode 55. 跳跃游戏 (中等)

题目大意:

给定一个非负整数数组 nums,你最初位于数组的第一个下标。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标。

思路:

不要去纠结"具体跳哪一步",而是关注"我最远能跳到哪"。

  • 贪心策略: 维护一个变量 max_reach,表示当前能够到达的最远位置
  • 遍历数组,如果你当前所在的位置 imax_reach 还要远,说明根本走不到这一步,失败。
  • 否则,尝试更新 max_reach = max(max_reach, i + nums[i])
  • 如果 max_reach 已经超过或等于最后一个位置,成功。

代码实现 (Python):

python 复制代码
def canJump(nums):
    max_reach = 0
    for i, jump in enumerate(nums):
        # 如果当前位置已经超过了最远能到达的范围,说明到不了这
        if i > max_reach:
            return False
        # 贪心:不断更新能跳到的最远边界
        max_reach = max(max_reach, i + jump)
    return True

3. LeetCode 45. 跳跃游戏 II (中等)

题目大意:

这题是上一题的进阶版。假设一定 能到达最后,求达到末尾所需的最小跳跃次数

思路:

想象在跑步,每一步都有一个"最远射程"。

  • 贪心策略: 不在乎每一小步跳哪,只在乎在当前这一跳的范围内,下一跳最远能跳到哪里。
  • 维护三个变量:jumps(跳了次数)、current_end(当前这一跳能到达的最远边界)、next_max_reach(下一跳最远能到的地方)。
  • 遍历数组,当走到 current_end 时,说明必须跳下一跳了,此时 jumps += 1,并把边界更新为 next_max_reach

代码实现 (Python):

python 复制代码
def jump(nums):
    jumps = 0
    current_end = 0      # 当前这步跳跃的最远边界
    next_max_reach = 0   # 下一步最远能跳到的位置
    
    # 注意:不需要遍历最后一个元素,因为到了倒数第二个如果能覆盖最后,就不用再跳了
    for i in range(len(nums) - 1):
        # 贪心:在当前范围内,寻找能跳得最远的落脚点
        next_max_reach = max(next_max_reach, i + nums[i])
        
        # 走到了当前这一跳的尽头
        if i == current_end:
            jumps += 1
            current_end = next_max_reach # 开启下一跳的范围
            
    return jumps

4. LeetCode 763. 划分字母区间 (中等)

题目大意:

给一个字符串 S。要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段长度的列表。
例如:S = "ababcbacadefegdehijhklij"
结果:[9, 7, 8](分别是 "ababcbaca", "defegde", "hijhklij")

思路:

关键点:同一个字母必须都在同一个片段里。 意味着如果一个片段里有字母 'a',那么这个片段至少要延伸到 'a' 最后一次出现的位置。

  1. 准备工作: 先遍历一遍字符串,记录每个字母最后一次出现的下标。
  2. 贪心策略: 再次遍历字符串,维护两个变量 startend
    • end 是当前片段中所有字母里,"最后出现位置"的最大值。
    • 当走到了 i == end 的时候,说明当前片段里的所有字母,在后面都不会再出现了。
    • 这就是一个完美的切割点!

代码实现 (Python):

python 复制代码
def partitionLabels(s):
    # 1. 统计每个字符最后出现的下标
    last_occurrence = {char: i for i, char in enumerate(s)}
    
    result = []
    start = 0
    end = 0
    
    # 2. 遍历字符串
    for i, char in enumerate(s):
        # 贪心:当前片段的终点,至少要是当前字符最后出现的位置
        end = max(end, last_occurrence[char])
        
        # 如果走到了当前片段的终点
        if i == end:
            result.append(end - start + 1) # 记录长度
            start = i + 1 # 更新下一个片段的起点
            
    return result

总结:如何学贪心?

  1. 不要想复杂: 贪心通常不需要高深的数学证明。就想:"此时此刻,怎么做最划算?"
  2. 找"最"字: 题目中出现"最大利润"、"最少跳跃"、"最远距离",往往可以考虑贪心。
  3. 试探法: 如果发现可以通过局部最优选法直接得到答案(且举不出反例),那么贪心就是对的。
  4. 常见模版:
    • 排序(很多贪心题需要先排序,虽然本页四题没用到,但很常见)。
    • 维护一个 max_so_far(目前为止最大)。
    • 双指针/滑动窗口辅助。
相关推荐
CoovallyAIHub5 小时前
让本地知识引导AI追踪社区变迁,让AI真正理解社会现象
深度学习·算法·计算机视觉
CoderCodingNo5 小时前
【GESP】C++ 二级真题解析,[2025年12月]第一题环保能量球
开发语言·c++·算法
yumgpkpm5 小时前
预测:2026年大数据软件+AI大模型的发展趋势
大数据·人工智能·算法·zookeeper·kafka·开源·cloudera
CoovallyAIHub5 小时前
AAAI 2026这篇杰出论文说了什么?用LLM给CLIP换了个“聪明大脑”
深度学习·算法·计算机视觉
Physicist in Geophy.5 小时前
一维波动方程(从变分法角度)
线性代数·算法·机器学习
im_AMBER5 小时前
Leetcode 115 分割链表 | 随机链表的复制
数据结构·学习·算法·leetcode
Liue612312315 小时前
【YOLO11】基于C2CGA算法的金属零件涂胶缺陷检测与分类
人工智能·算法·分类
!!!!8135 小时前
蓝桥备赛Day1
数据结构·算法
Mr_Xuhhh5 小时前
介绍一下ref
开发语言·c++·算法