Day28 貪心演算法part2

haohaoscnblogs發表於2024-08-13

任務

122.買賣股票的最佳時機 II

給你一個整數陣列 prices ,其中 prices[i] 表示某支股票第 i 天的價格。

在每一天,你可以決定是否購買和/或出售股票。你在任何時候 最多 只能持有 一股 股票。你也可以先購買,然後在 同一天 出售。

返回 你能獲得的 最大 利潤 。

思路

考慮分解最終利潤,比如第3天賣,第0天買,第3天賣。利潤為p[3]-p[0] == p[3]-p[2]+p[2]-p[1]+p[1]-p[0],也即是你隔了幾天的買賣,都可以分解成連續買賣,即第三天賣,第0天買,就是第0天買,第1天賣,第2天買,第3天賣的組合,因此每天買賣的利潤可以涵蓋隔天買賣的利潤。
每天都買賣,只收集每天的正利潤。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        result = 0
        for i in range(1,len(prices)):
            if prices[i] - prices[i-1] > 0:
                result +=  prices[i] - prices[i-1]
        return result

55. 跳躍遊戲

給你一個非負整數陣列 nums ,你最初位於陣列的 第一個下標 。陣列中的每個元素代表你在該位置可以跳躍的最大長度。

判斷你是否能夠到達最後一個下標,如果可以,返回 true ;否則,返回 false 。

思路

考慮覆蓋,每次走到能覆蓋的最大部分,走的過程中記錄更新覆蓋。

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        if len(nums) == 0: return True
        cover = 1 #右開區間
        #for i in range(cover+1): #py中for迴圈不能修改迴圈變數!!!
        i = 0
        while i < cover:
            cover = max(i+nums[i]+1,cover)
            if cover >= len(nums):
                return True
            i+=1
        return False

45. 跳躍遊戲 II

給定一個長度為 n 的 0 索引整數陣列 nums。初始位置為 nums[0]。
每個元素 nums[i] 表示從索引 i 向前跳轉的最大長度。換句話說,如果你在 nums[i] 處,你可以跳轉到任意 nums[i + j] 處:

  • 0 <= j <= nums[i]
  • i + j < n
    返回到達 nums[n - 1] 的最小跳躍次數。生成的測試用例可以到達 nums[n - 1]。

思路

同樣考慮覆蓋,curCover和nextCover分別表示當前最大覆蓋和下次最大覆蓋,遍歷整個陣列的過程中更新這兩個值,每次達到當前最大覆蓋時,計數加1,當下次最大覆蓋達到或超過陣列長度時,統計結束。這個得模擬著來看,不是很直觀和好想,關鍵難度在編碼上,就是對nextCover和curCover在模擬過程中的修改。

class Solution:
    def jump(self, nums: List[int]) -> int:
        if len(nums) == 1: return 0
    
        curCover = 0
        nextCover = 0
        result = 0
        for i in range(len(nums)):
            nextCover = max(nextCover,nums[i]+i)
            if i == curCover:
                result += 1
                curCover = nextCover
                if nextCover >= len(nums)-1:
                    break
        return result   

1005. K 次取反後最大化的陣列和

思路

絕對值從大到小排序,然後順序遍歷,儘量將負數變成正數,如果遍歷完K仍然大於0且為奇數,則將絕對值最小的值取反。關鍵在於Py中自定義排序和lambda表示式的寫法

class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        nums.sort(key=abs,reverse=True)
        
        for i in range(len(nums)):
            if k > 0 and nums[i] < 0: # 儘可能的把絕對值較大的負數變正
                nums[i] *=-1
                k-=1
        if k%2 == 1: #K剩餘奇數,如果k>0 說明陣列已經全為正數,則找絕對值最小的取反
            nums[-1] *= -1
        
        res = 0
        for i in range(len(nums)):
            res += nums[i]
        return res

心得體會

  • 買賣股票的時機系列問題後續可用動規解決,比較通用,只是多次買賣這道題恰好可用貪心比較簡單
  • 跳躍遊戲中,更新覆蓋的思路很難想到,特別是跳躍遊戲II中的next和cur的更新。

相關文章