理论基础
https://programmercarl.com/%E8%B4%AA%E5%BF%83%E7%AE%97%E6%B3%95%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
- 贪心算法的本质:由局部最优推到全局最优
- 贪心算法的套路:无固定套路
455.分发饼干
https://programmercarl.com/0455.%E5%88%86%E5%8F%91%E9%A5%BC%E5%B9%B2.html
- 考点
- 贪心算法
- 我的思路
- 将胃口和饼干数组排序
- 大胃口给大饼干
- 两层for循环,一层遍历胃口,一层遍历饼干
- 视频讲解关键点总结
- 无视频
- 文字讲解的重点在于降低算法的时间复杂度
- 把饼干的那重循环利用if判断替换
- 我的思路的问题
- 时间复杂度高
- 代码书写问题
- 无
- 可执行代码
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
index = len(s) - 1
result = 0
for i in range(len(g) - 1, -1, -1):
if index >= 0 and s[index] >= g[i]:
result += 1
index -= 1
return result
*376. 摆动序列
https://programmercarl.com/0376.%E6%91%86%E5%8A%A8%E5%BA%8F%E5%88%97.html
- 考点
- 贪心算法(二刷用的动态规划,比较好理解也好写)
- 我的思路
- 无思路
- 视频讲解关键点总结
- 二刷用的动规,因此这里先写动规的思路:
- dp数组的含义是,到当前元素i的位置时,对应的最长摆动序列是多长;其中每个i对应2个状态,状态0是当前元素i扮演山峰的角色(值比序列中的前后元素大),状态1是当前元素扮演山谷的角色(值比序列中的前后元素小)
- 递推公式,当前元素i的dp值应遍历从头开始到i的每个元素j,并比较其与i的大小来进行更新,如果j比i大,则i扮演山谷角色,此时dp[i][1] = max(dp[i][1], dp[j][0] + 1);j比i小,i扮演山峰角色,此时dp[i][0] = max(dp[i][0], dp[j][1] + 1)
- 初始化,由于题目中说了只有一个元素也算摆动序列,所以dp值最小为1,因此初始化为1
- 循环遍历,双层,外层遍历i,内层遍历j
- 以下为贪心的思路:
- 关键点1:只需要遇到摆动点记录一次长度即可,不需要更改原序列
- 关键点2:除了前后差值异号的情况,还有前差值为0、后差值存在的情况
- 对于前差值为0的情况,又分为单调递增中包含平台的情况和摆动中包含平台的情况
- 关键点3:头尾元素也被记录为一次摆动
- 二刷用的动规,因此这里先写动规的思路:
- 我的思路的问题
- 无思路
- 代码书写问题
- 无
- 可执行代码
# 动态规划思路代码
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
dp = [[1] * 2 for _ in range(len(nums))]
for i in range(len(nums)):
for j in range(i):
if nums[j] < nums[i]:
dp[i][0] = max(dp[i][0], dp[j][1] + 1)
elif nums[j] > nums[i]:
dp[i][1] = max(dp[i][1], dp[j][0] + 1)
return max(dp[-1][0], dp[-1][1])
# 贪心思路代码
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
pre_diff = 0
cur_diff = 0
result = 1
for i in range(len(nums) - 1):
cur_diff = nums[i + 1] - nums[i]
if (pre_diff <= 0 < cur_diff) or (pre_diff >= 0 > cur_diff):
result += 1
pre_diff = cur_diff
return result
*53. 最大子序和
https://programmercarl.com/0053.%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%92%8C.html
- 考点
- 贪心算法
- 我的思路
- 无思路
- 视频讲解关键点总结
- 暴力解法
- 双层for循环,计算所有连续子序列的和,然后找最大值
- 贪心解法
- 如果当前和值为负数,则一定对后续和有削减作用,因此一到和值为复数,就将当前累加和归为0,重新开始
- 在过程中记录最大值
- 暴力解法
- 我的思路的问题
- 无思路
- 代码书写问题
- 可以用
float('-inf')
取极小值
- 可以用
- 可执行代码
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
summ = 0
max_num = float('-inf')
for i in range(len(nums)):
summ += nums[i]
if summ > max_num:
max_num = summ
if summ < 0:
summ = 0
return max_num