理论基础
通过局部最优解去找到全局最优解,贪心有时候就是常识性推导,并不存在什么模板或者规律,将问题拆解完成问题即可。
455.分发饼干
分析过程:
大尺寸的饼干既可以满足胃口大的孩子,也可以满足胃口小的孩子,因而可以先优先满足胃口比较大的孩子。
局部最优:大饼干喂给胃口大的孩子,充分利用饼干尺寸喂饱一个
全局最优:喂饱尽可能多的小孩
具体实现方法:for循环遍历,利用自减的方式减少另一个数组的遍历
# 注意本题不需要使用两个循环数组进行求解,这样会增加程序运行的工作量
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
# 贪心用最大的饼干去满足最大的胃口
count = 0
s = sorted(s)
g = sorted(g)
# 饼干的数组下标
index = len(s)-1
for i in range(len(g)-1,-1,-1): #胃口
# 只有当当前的胃口小于最大的饼干时,才能遍历下一个胃口
if index >= 0 and g[i] <= s[index]:
index -= 1
count += 1
return count
376. 摆动序列
技巧: 利用prediff和curdiff对上坡和下坡进行判定。
贪心算法: 让峰值尽可能的保持峰值,然后删除单一坡度上的节点,即需要删除。要点在于如何对峰值进行统计
确定题目的大体思路之后,需要进一步考察三种情况:
- 情况一:上下坡中有平坡
- 情况二:数组首尾两端
- 情况三:单调坡中有平坡
题解的处理方法: 因为在本题中判断坡度的上升与下降主要使用的是后一个元素与前一个元素之间的差值,所以可以通过prediff和curdiff来区分这种情况。
峰值的条件:(preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)
数组的首尾两端:统一规则对开头可以在加一个prediff=0的数值
单调坡中有平坡:
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
# 根据坡度的改变程度确定prediff和curdiff
# 进行剪枝
if len(nums) <= 1 : return len(nums)
curdiff = 0 # 当前的插值
prediff = 0
result = 1
for i in range(len(nums)-1):
curdiff = nums[i+1]-nums[i]
if (prediff <= 0 and curdiff > 0) or (prediff >= 0 and curdiff < 0 ):
prediff = curdiff
result += 1
return result
53. 最大子序和
- 不要忘记暴力求解:实在想不到解决方法就是用暴力求解的方法。
- 贪心解法:遍历nums,从头开始用count累积,如果count一旦加上nums[i]变为负数,那么就应该从nums[i+1]开始从0累积count了,因为已经变为负数的count,只会拖累总和。
如果-2和1在一起的时候一定是从1开始因为,两者相加已经为负了一定会拉低总体的和,所以应该从1开始。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
# 和另一个双指针的问题不同:双指针需要满足的是区间的性质。
if len(nums)==1 : return nums[0]
result = -float("inf")
count = 0
# 看当前值的求和情况,如果当前值的和大于result的值那么将当前值复制,如果count值小于0说明当前的序列不能够满足的话,则直接将当前值归零。
for i in range(len(nums)):
count += nums[i]
if count > result:
result = count
if count <= 0:
count = 0
return result