贪心算法理论基础
455.分发饼干
代码随想录:455.分发饼干
Leetcode:455.分发饼干
做题
将饼干和小孩都按降序排序,再依次满足。
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort(reverse=True)
s.sort(reverse=True)
res = 0
i = j = 0
if len(s) == 0 or len(g) == 0:
return 0
while i < len(s):
if s[i] >= g[j]:
res += 1
i += 1
j += 1
if j >= len(g):
break
return res
看文章
大饼干优先
class Solution:
def findContentChildren(self, g, s):
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
时间复杂度:O(nlogn)
空间复杂度:O(1)
小饼干优先
class Solution:
def findContentChildren(self, g, s):
g.sort() # 将孩子的贪心因子排序
s.sort() # 将饼干的尺寸排序
index = 0
for i in range(len(s)): # 遍历饼干
if index < len(g) and g[index] <= s[i]: # 如果当前孩子的贪心因子小于等于当前饼干尺寸
index += 1 # 满足一个孩子,指向下一个孩子
return index # 返回满足的孩子数目
时间复杂度:O(nlogn)
空间复杂度:O(1)
376. 摆动序列
代码随想录:376. 摆动序列
Leetcode:376. 摆动序列
做题
有初始思路,比较简单,需要调试解决特殊情况。用一个bool变量来记录前面是上升还是下降,当bool变化时就res += 1,当前面平峰时需要特殊处理。具体代码如下:
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
size = len(nums)
if size == 1: return 1
if size == 2:
if nums[0] != nums[1]:
return 2
else:
return 1
res = 1
level = True
for i in range(1, size):
cur = nums[i] - nums[i-1]
if i == 1:
if cur > 0:
is_lift = True
level = False
res += 1
elif cur < 0:
is_lift = False
level = False
res += 1
else:
if level and cur > 0:
level = False
is_lift = True
res += 1
elif level and cur < 0:
level = False
is_lift = False
res += 1
elif level:
continue
elif is_lift and cur < 0:
res += 1
is_lift = False
elif not is_lift and cur > 0:
res += 1
is_lift = True
return res
时间复杂度:O(n)
空间复杂度:O(1)
看文章
计算prediff和curdiff,考虑三种情况:上下坡中有平坡、数组首尾两端、单调坡中有平坡。具体思路看文章。也可以用动态规划。这里感觉太繁琐了,暂时不看。
53. 最大子序和
代码随想录:53. 最大子序和
Leetcode:53. 最大子序和
做题
无贪心算法思路。
看文章
暴力求解
C++可能能过,其他语言不一定
时间复杂度:O(n^2)
空间复杂度:O(1)
贪婪算法
局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
全局最优:选取最大“连续和”。
局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。
从代码角度上来讲:遍历 nums,从头开始用 count 累积,如果 count 一旦加上 nums[i]变为负数,那么就应该从 nums[i+1]开始从 0 累积 count 了,因为已经变为负数的 count,只会拖累总和。
时间复杂度:O(n)
空间复杂度:O(1)
按照思路自己实现了代码:
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
res = float('-inf')
cur = 0
for i in range(len(nums)):
cur += nums[i]
res = max(cur, res)
if cur < 0:
cur = 0
return res
以往忽略的知识点小结
- 贪心算法没什么“思路”,可能就是用简单的思路尝试,然后不断调试,处理特殊情况
个人体会
完成时间:1h40min。
心得:贪心算法比较没“思路”,但特殊情况分析还挺麻烦的,最好自己尝试,看文章有点难进入思路。