贪心算法理论基础
重要知识点
1)贪心的本质是选择每一阶段的局部最优,从而达到全局最优
2)通过模拟和举反例来测试是否用贪心算法,无固定的套路
3)贪心算法一般分为如下四步:
(1)将问题分解为若干个子问题
(2)找出适合的贪心策略
(3)求解每一个子问题的最优解
(4)将局部最优解堆叠成全局最优解
也可以是思考思路,不一定按这个步骤写
455.分发饼干
1.题目
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
2.实现
最开始是用最小的饼干去喂最大的食量,但这样不能简化思路,且还得考虑如果小饼干n不满足大胃王,能否满足胃口稍微小的
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g = sorted(g)
s = sorted(s)
n = len(g)
m = len(s)
cnt, j = 0, 0
for i in range(n):
while j < m:
if s[j] >= g[i]:
cnt += 1
j += 1
break
j += 1
return cnt
3.文章讲解
376. 摆动序列
1.题目
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。
2.实现
思路基本和题解一致
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
# 16 -12 5 3 2 -5 11 -8
cnt = 0
n = len(nums)
if n == 1:
return 1
pre = nums[1] - nums[0]
if pre != 0:
cnt = 1
i = 2
while i < n:
cur = nums[i] - nums[i - 1]
if cur == 0:
i += 1
continue
if (pre == 0 and cur != 0) or (pre * cur < 0):
pre = cur
cnt += 1
i += 1
return cnt + 1
3.文章讲解
看到这个峰谷的图就明白了
53. 最大子序和
1.题目
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
2.实现
难点:
1)终止条件
2)在满足条件后一定要及时更新结果,以及何时更新结果
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
res = nums[0]
n = len(nums)
if n == 1:
return nums[0]
i, j = 0, 1
tmp = nums[0]
while j < n and i < n:
if nums[j] + tmp > nums[j]:
tmp += nums[j]
res = tmp if res < tmp else res
j += 1
else:
i = j
j = i + 1
tmp = nums[i]
res = tmp if res < tmp else res # 考虑此时nums[i]也可能为和最大解
return res
3.文章讲解
本题是O(n)的时间复杂度,也可以用dp来解决