day23-数据结构力扣

回溯结束,开始贪心算法。

说是贪心没啥规律,不会就去看题解

理论基础

贪心的本质

贪心 = 每一步都选局部最优 → 最终达到全局最优

  • 局部最优:当前这一步能拿到的最好结果

  • 全局最优:整个问题的最终最优解

  • 不回头、不反悔、不看未来,只选当下最好


什么时候能用贪心

满足一条就能试贪心:

  1. 局部最优可以推出全局最优

  2. 举不出反例(找不到让贪心失效的情况)

  3. 问题不能用动态规划(比如背包问题不能用贪心)


贪心有没有套路?

没有固定模板、没有固定公式!

  • 不像回溯 / DFS 有标准框架

  • 贪心靠常识 + 模拟 + 举反例

  • 面试不需要数学证明,能自圆其说即可


贪心通用解题四步

  1. 把问题拆成一步一步的小决策

  2. 想清楚:每一步的局部最优是什么

  3. 按局部最优去做选择

  4. 验证:这样做能不能得到全局最优(举反例)

455.分发饼干

题目链接455. 分发饼干 - 力扣(LeetCode)

思路

感觉简单吧,又写不对,提交通过了17个

python 复制代码
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        count=0
        for i in g:
            if i in s:
                count+=1
        return min(count,len(s))

好吧,没我想的那么简单,还要用双指针

小饼干喂胃口小的,大饼干喂胃口大的,能喂就喂,不能喂就跳过。

步骤

  1. 把孩子胃口 g 和饼干 s 都从小到大排序

  2. 用两个指针分别指向当前孩子、当前饼干

  3. 饼干 ≥ 胃口 → 喂饱,两个指针都后移

  4. 饼干 < 胃口 → 饼干太小,换更大的

提交

python 复制代码
from typing import List

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()
        s.sort()
        
        i = j = res = 0
        while i < len(g) and j < len(s):
            if s[j] >= g[i]:
                res += 1
                i += 1
                j += 1
            else:
                j += 1
        return res

376. 摆动序列

题目链接376. 摆动序列 - 力扣(LeetCode)

思路

我的第一版错误代码

python 复制代码
class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        minus=[]
        for i in range(len(nums)-1):
            minus.append(nums[i+1]-nums[i])
        count=0
        for i in range(len(minus)-1):
            if minus[i]*minus[i+1]<0:
                count+=1
            else:
                break   # 这里大错特错!不能停!
        return count+2
  • 只要遇到不摆动就 break,直接停了

  • 边界处理错误全递增、全递减、全 0 会算错。

正确思路:

1.处理短数组

python 复制代码
if len(nums) <= 1:
    return len(nums)
  • 数组长度 0 → 0

  • 长度 1 → 1这是边界条件

2.计算相邻差值,并去掉 0

python 复制代码
for i in range(len(nums)-1):
    diff = nums[i+1] - nums[i]
    if diff != 0:
        minus.append(diff)
  • 差值 = 后 - 前

  • =0 的不要(平坡不算摆动)

  • 最后得到一个只有正数、负数的差值列表

3. 如果全是平坡,返回 1

python 复制代码
if not minus:
    return 1

4. 统计正负交替的次数

python 复制代码
count = 0
for i in range(len(minus)-1):
    if minus[i] * minus[i+1] < 0:
        count += 1
  • 两个数相乘 < 0 → 一正一负,交替了!

  • 每交替一次,count + 1

5. 最终答案 = 交替次数 + 2

  • 统计了 count 次交替

  • 最终长度 = 交替次数 + 第一个数 + 第二个数 = count + 2

提交

python 复制代码
from typing import List

class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        if len(nums) <= 1:
            return len(nums)
        
        minus = []
        for i in range(len(nums)-1):
            diff = nums[i+1] - nums[i]
            if diff != 0:  # 跳过平的
                minus.append(diff)
        
        if not minus:
            return 1
        
        count = 0
        for i in range(len(minus)-1):
            # 正负交替就计数
            if minus[i] * minus[i+1] < 0:
                count += 1
        
        return count + 2

53. 最大子序和

题目链接 53. 最大子数组和 - 力扣(LeetCode)

思路

正确思路(Kadane 算法)

核心一句话:当前数字,要么加入前面的子数组,要么自己重新开始一段。

具体规则:

  1. 维护一个 current_max:表示以当前位置结尾的最大子数组和
  2. 维护一个 global_max:记录遍历过程中出现过的最大值
  3. 对每个数:
    • current_max = max(nums[i], current_max + nums[i])
    • global_max = max(global_max, current_max)

为什么?

  • 如果前面的和是负的,加上我只会更小 → 我自己重新开始
  • 如果前面的和是正的,加上我会更大 → 加入前面

示例

nums = [-2,1,-3,4,-1,2,1,-5,4]

  • current_max = -2, global_max = -2
  • 1 → max(1, -2+1= -1) → current=1, global=1
  • -3 → max(-3, 1-3=-2) → current=-2, global=1
  • 4 → max(4, -2+4=2) → current=4, global=4
  • -1 → max(-1, 4-1=3) → current=3, global=4
  • 2 → max(2, 3+2=5) → current=5, global=5
  • 1 → max(1,5+1=6) → current=6, global=6
  • -5 → max(-5,6-5=1) → current=1, global=6
  • 4 → max(4,1+4=5) → current=5, global=6

最终返回 6

提交

python 复制代码
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        current_max = global_max = nums[0]
        
        for num in nums[1:]:
            # 要么自己重新开始,要么接上前面
            current_max = max(num, current_max + num)
            # 更新全局最大
            global_max = max(global_max, current_max)
        
        return global_max
相关推荐
Robot_Nav2 小时前
RC-ESDF 详解:以机器人为中心的欧几里得有符号距离场
人工智能·算法·机器人
田梓燊2 小时前
leetcode 234
算法·leetcode·职场和发展
Aaron15882 小时前
RFSOC+VU13P中在线部分可重构技术的应用分析
人工智能·算法·matlab·fpga开发·重构·信息与通信·信号处理
yashuk2 小时前
C语言入门教程:程序结构与算法举例
c语言·算法·教程·程序设计·开发过程
zsc_1182 小时前
pvz3解码小游戏求解算法 (二)
算法
hanbr2 小时前
每日一题day1(Leetcode 76最小覆盖子串)
算法·leetcode
AI科技星2 小时前
张祥前统一场论中两个电荷定义的统一性解析
开发语言·线性代数·算法·数学建模·平面
代码地平线2 小时前
C语言实现堆与堆排序详解:从零手写到TopK算法及时间复杂度证明
c语言·开发语言·算法
小江的记录本2 小时前
【大语言模型】大语言模型——核心概念(预训练、SFT监督微调、RLHF/RLAIF对齐、Token、Embedding、上下文窗口)
java·人工智能·后端·python·算法·语言模型·自然语言处理