目录
- 455. 分发饼干(总出问题,需要多次写)
- 1、题目描述
- 2、思路
- 3、code
- 4、复杂度分析
- 5、超级无敌一句话总结
- 376. 摆动序列
- 1、题目描述
- 2、思路
- 4、复杂度分析
- 53. 最大子数组和
- 1、题目描述
- 2、思路
- 3、code
- 4、复杂度分析
455. 分发饼干(总出问题,需要多次写)
题目链接:link
1、题目描述
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是满足尽可能多的孩子,并输出这个最大数值。
示例 1:
输入: g = [1,2,3], s = [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3 个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是 1,你只能让胃口值是 1 的孩子满足。
所以你应该输出 1。
2、思路
🥵贪心思路:尽量用大饼干来喂大胃口的孩子
💔容易出错的地方: 到底要怎么转到下一个饼干或者下一个胃口(本人总是搞不明白)
饼干i = [3,2,1]
胃口j = [6,2,1]
对于饼干3, 胃口6 不能满足 ➡️ 胃口+1
对于饼干3, 胃口2 能满足 ➡️ 饼干+1 胃口+1
对于饼干2, 胃口1 能满足 ➡️ 饼干+1 胃口+1
胃口个数到达最大值 🆗
# 对应代码
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
s.sort(reverse = True)
g.sort(reverse = True)
res = 0
i = 0
j = 0
while (i<len(s)) and (j<len(g)):
if s[i]<g[j]:
j+=1
else:
i+=1
j+=1
res += 1
return res
3、code
上一个思路的可以看出胃口是在每一轮都要到下一个的,因为不满足就说明最大的🍪都满足不了这个孩子的胃口;如果满足就说明这个孩子可以被喂饱,也要转到下一个孩子
所以可以遍历胃口,当🍪大于胃口的时候,转到下一个🍪(代码随想录的思路 )
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
s.sort(reverse = True)
g.sort(reverse = True)
res = 0
i = 0
for weikou in g:
if i < len(s) and s[i] >= weikou:
res+=1
i+=1
return res
4、复杂度分析
1️⃣ 时间复杂度:
O
(
N
)
O(N)
O(N)
2️⃣ 空间复杂度:
O
(
!
)
O(!)
O(!)
5、超级无敌一句话总结
尽量用大饼干来喂大胃口的孩子,如果遍历思路不清晰,可以拿例子试一下,就知道什么时候该+1了
376. 摆动序列
题目链接:link
1、题目描述
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。
相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。
给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。
2、思路
🤔摆动序列什么意思?
比如17这个点,前一个数为1,后一个数为5,17-1=16是正数,5-17=-12是负数,那么1,17,5就是一个摆动序列✅
比如10这个点,前一个数为5,后一个数为15,10-5 = 5是正数,15-5=5也为正数,那么5,10,15就不是一个摆动序列❌
所以就找到前后梯度相反的节点就是摆动序列,也就是说山区前后节点梯度相同的序列就是子摆动序列
🥵特殊情况:前一个梯度和后一个梯度为0,也就是平坡的情况
1️⃣ 超级无敌傻思路:先把数组中的平坡删掉
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
if len(nums) == 1:
return 1
# 先把平坡删掉
new_nums = [nums[0]]
pre = nums[0]
for i in range(1,len(nums)):
if nums[i] != pre:
new_nums.append(nums[i])
pre = nums[i]
print(new_nums)
# 单纯的找极值问题
if len(new_nums) <= 2:
return len(new_nums)
res = 2
prediff = new_nums[1] - new_nums[0]
for i in range(1,len(new_nums)-1):
curdiff = new_nums[i+1] - new_nums[i]
# prediff = new_nums[i] - new_nums[i-1]
if (curdiff > 0 and prediff < 0) or (curdiff < 0 and prediff > 0):
res += 1
prediff = curdiff
return res
2️⃣ 把平坡当成特殊情况来考虑
平坡有两种情况:
🅰️情况一:上下坡中有平坡
这里面中间有4个2,我只想留下一个,同意规定就是留下最右边的2,可以看到这个2的点,前一个梯度为0,后一个梯度为-1,也就是说要把这种情况加到计算长度的情况里面:
if (curdiff > 0 and prediff <= 0) or (curdiff < 0 and prediff >= 0):
res += 1
🅱️情况二:单调坡度有平坡
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
if len(nums) == 1:
return 1
pre = 0
cur = 0
res = 1 # 记录峰值个数,序列默认序列最右边有一个峰值
for i in range(len(nums)-1):
cur = nums[i+1] - nums[i]
if (cur > 0 and pre <= 0) or (cur < 0 and pre >= 0):
pre = cur
res += 1
return res
4、复杂度分析
1️⃣ 时间复杂度:
O
(
N
)
O(N)
O(N)
2️⃣ 空间复杂度:
O
(
1
)
O(1)
O(1)
53. 最大子数组和
题目链接:link
1、题目描述
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
2、思路
🍬局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
3、code
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
res = nums[0]
max_res = res
for i in range(1,len(nums)):
if res<0:
res = nums[i]
else:
res += nums[i]
max_res = max(max_res,res)
return max_res
4、复杂度分析
1️⃣ 时间复杂度:
O
(
N
)
O(N)
O(N)
2️⃣ 空间复杂度:
O
(
1
)
O(1)
O(1)