1. 程式人生 > 其它 >1423. 可獲得的最大點數

1423. 可獲得的最大點數

技術標籤:LeetCodepythonleetcode子陣列

1423. 可獲得的最大點數

難度中等

幾張卡牌排成一行,每張卡牌都有一個對應的點數。點數由整數陣列cardPoints給出。每次行動,你可以從行的開頭或者末尾拿一張卡牌,最終你必須正好拿k張卡牌。你的點數就是你拿到手中的所有卡牌的點數之和。

給你一個整數陣列cardPoints和整數k,請你返回可以獲得的最大點數。

示例 1:
輸入:cardPoints = [1,2,3,4,5,6,1], k = 3
輸出:12
解釋:第一次行動,不管拿哪張牌,你的點數總是 1 。但是,先拿最右邊的卡牌將會最大化你的可獲得點數。最優策略是拿右邊的三張牌,最終點數為 1 + 6 + 5 = 12 。

示例 2:
輸入:cardPoints = [2,2,2], k = 2
輸出:4
解釋:無論你拿起哪兩張卡牌,可獲得的點數總是 4 。

示例 3:
輸入:cardPoints = [9,7,7,9,7,7,9], k = 7
輸出:55
解釋:你必須拿起所有卡牌,可以獲得的點數為所有卡牌的點數之和。

第一版程式碼(先取最後的K個數作為最初的結果, 然後每次向後移動一位, 同時從最前面取一個數字, 依次進行, 直到取的是最前面得K個數字, 其中最大的陣列和就是結果)

class Solution:
    def maxScore(self, cardPoints: List[int], k: int) -> int:
        res = sum(cardPoints[-k:])
        for i in range(1, k + 1):
            if i == k:
                li = cardPoints[:i]
            else:
                li = cardPoints[:i] + cardPoints[-(k-i):]
            tem = sum(li)
            if tem > res:
                res = tem
        return res

結果直接超出了時間限制, 因為每次都在求K個元素的和, 比較耗時

第二版程式碼(可以簡化為取陣列最後的K個數字,和取資料最前的K個數字組成新的陣列, 從中選取最大的K的子串,這次每次移動的時候就是減一個數字, 加一個數字, 不用每次都求和)

class Solution:
    def maxScore(self, cardPoints: List[int], k: int) -> int:
        li = cardPoints[-k:] + cardPoints[:k]
        res = temp = sum(li[:k])
        left, right = 1, k
        while right < 2*k:
            temp = temp - li[left - 1] + li[right]
            if temp > res:
                res = temp
            right += 1
            left += 1
        return res

結果還不錯

第三版程式碼(我們再考慮一下特殊情況, 就是當陣列的長度就是K的時候, 我們直接求和即可)

class Solution:
    def maxScore(self, cardPoints: List[int], k: int) -> int:
        if k == len(cardPoints):
            return sum(cardPoints)
            
        li = cardPoints[-k:] + cardPoints[:k]
        res = temp = sum(li[:k])
        left, right = 1, k
        while right < 2 * k:
            temp = temp - li[left - 1] + li[right]
            if temp > res:
                res = temp
            right += 1
            left += 1
        return res