任務
455. 分發餅乾
假設你是一位很棒的家長,想要給你的孩子們一些小餅乾。但是,每個孩子最多隻能給一塊餅乾。
對每個孩子 i,都有一個胃口值 g[i],這是能讓孩子們滿足胃口的餅乾的最小尺寸;並且每塊餅乾 j,都有一個尺寸 s[j] 。如果 s[j] >= g[i],我們可以將這個餅乾 j 分配給孩子 i ,這個孩子會得到滿足。你的目標是儘可能滿足越多數量的孩子,並輸出這個最大數值。
思路
對s和g排序,每次所能滿足的最大胃口的孩子,計數。注意要從胃口開始倒序遍歷,索引自然遞減,而對於尺寸的遞減,則透過index的形式,每用掉一個,遞減,並且統計分配數量。
注意自然遞減不能用尺寸,模擬一下可以發現
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
s.sort()
g.sort()
index = len(s)-1
count = 0
for i in range(len(g)-1,-1,-1): #這裡必須遍歷g而非s
if index >=0 and g[i] <= s[index]:
count += 1
index -= 1
return count
376. 擺動序列
如果連續數字之間的差嚴格地在正數和負數之間交替,則數字序列稱為 擺動序列 。第一個差(如果存在的話)可能是正數或負數。僅有一個元素或者含兩個不等元素的序列也視作擺動序列。
例如, [1, 7, 4, 9, 2, 5] 是一個 擺動序列 ,因為差值 (6, -3, 5, -7, 3) 是正負交替出現的。
相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是擺動序列,第一個序列是因為它的前兩個差值都是正數,第二個序列是因為它的最後一個差值為零。
子序列 可以透過從原始序列中刪除一些(也可以不刪除)元素來獲得,剩下的元素保持其原始順序。
給你一個整數陣列 nums ,返回 nums 中作為 擺動序列 的 最長子序列的長度 。
思路
本題很難想,最基礎的思路是,用prevDiff和nextDiff記錄當前的節點的前後diff,如果異號,則說明可以保留並且統計加1,即基礎條件為if preDiff >0 and nextDiff < 0 or preDiff<0 and nextDiff > 0,然後遍歷過程中prevDiff隨著nextDiff修改
- 情況一: 首尾節點的處理,首節點,假裝之前還有一個和他相等的節點,那麼是否統計第一個節點只看和第二個節點的關係即nextDiff,為了統一邏輯,則上面的基礎條件變為 if preDiff >= 0 and nextDiff < 0 or preDiff<=0 and nextDiff > 0
- 情況二: 非單調有平坡,可以延續情況一的邏輯
- 情況三: 單調有平坡,將修改時機從 遍歷過程中prevDiff隨著nextDiff修改 改為,只有發生方向變化時,才修改prevDiff,這個很難想到
從看完題解再分析,可以分析思路是找到需要保留的節點,因為最終形成的是擺動序列,所以最終形成的prev,diff是隻記錄方向變化的
class Solution376:
def wiggleMaxLength(self, nums: List[int]) -> int:
if len(nums) == 1:
return 1
preDiff = 0
nextDiff = 0
result = 1 # 預設最後一個為一個波動
for i in range(len(nums)-1):
nextDiff = nums[i+1] - nums[i]
if preDiff >= 0 and nextDiff < 0 or preDiff<=0 and nextDiff > 0:
result +=1
preDiff = nextDiff # 只有方向改變時才修改prediff、
return result
53. 最大子陣列和
給你一個整數陣列 nums ,請你找出一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。
子陣列是陣列中的一個連續部分。
思路
暴力的解法是找到每一個索引為首的最大和連續子陣列,複雜度為O(n^2)。
考慮動規的解法,dp[i]表示以當前索引i為結尾的最大子陣列和,那麼dp[i-1]表示以索引i-1為結尾的最大子陣列和,dp[i]就取包含以i-1結尾的子序列和不包含以i-1結尾的子序列兩種情況中的最大值,即dp[i] = max(dp[i-1]+nums[i],nums[i])
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
dp = [0] * len(nums) # dp陣列的元素: 以當前索引i結尾的最大和連續子陣列的長度
dp[0] = nums[0]
for i in range(1,len(nums)):
dp[i] = max(dp[i-1]+nums[i],nums[i])
return max(dp)
貪心思路:當遍歷到某個數和為負數時,則以下一個數為起點,重新累加
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
result = float("-inf")
sum = 0
for i in range(len(nums)):
sum += nums[i]
result = sum if result<sum else result
if sum < 0:
sum = 0
return result
心得體會
貪心法的思路非常靈活,且是用區域性最優來嘗試是否達到全域性最優,其中的證明也是比較困難的,現階段還無法嚴格證明,只能去模擬看是否可以透過,或無法舉出反例的情況,可以鍛鍊一定的思維能力,想不出來可以看題解,看懂思路後編碼即可,不必追求完美。本章的目標就是理解思路後的編碼能力.