2270. Number of Ways to Split Array
2270. Number of Ways to Split Array
此道題目需要先理解 Prefix Sum 的概念比較好做,如果可以理解的話這個題目只有一個地方比較難,那就是為什麼在把題目陣列分左右兩側的邏輯中,for 迴圈需要在最後減一?
class Solution:
def waysToSplitArray(self, nums: List[int]) -> int:
prefix = [nums[0]]
for i in range(1, len(nums)):
prefix.append(prefix[len(prefix) - 1] + nums[i])
valid = 0
for i in range(len(prefix) - 1):
front = prefix[i]
end = prefix[len(prefix) - 1] - prefix[i]
if front >= end:
valid += 1
return valid
這裡的 - 1
是為了 避免最後一個元素成為前半部分的結尾,從而確保陣列被正確地拆分為兩個部分。
這道題的目標是找出能夠將 nums
陣列分成兩部分 (nums[0:i], nums[i:])
,並且滿足:
$$\text{前半部分的總和} \geq \text{後半部分的總和}$$
根據程式碼,prefix[i]
代表前 i+1
個元素的總和,而 end = prefix[len(prefix) - 1] - prefix[i]
代表後半部分的總和。
為何 range(len(prefix) - 1)
?
prefix
的長度與 nums
相同,而有效的切割點最多只能到倒數第二個位置,不能到最後一個位置。例如:
nums = [2, 3, 1, 5]
對應的 prefix
陣列:prefix = [2, 5, 6, 11]
可能的切割點 (i
的範圍):
i = 0: front = 2, end = 9
i = 1: front = 5, end = 6
i = 2: front = 6, end = 5 (符合條件)
此時 i
只能取 0 ~ len(prefix) - 2
,即 range(len(prefix) - 1)
。
如果 i == len(prefix) - 1
,那麼:
front = prefix[len(prefix) - 1]
(即整個陣列的總和)end = prefix[len(prefix) - 1] - prefix[len(prefix) - 1] = 0
→ 這樣會導致沒有後半部分,違反題目要求。
優化
在這個題目中,其實有一項一直是常數,那就是在計算 end
時,我們都是取 prefix sum 的最後一個數字,也就是說如果我們能知道全部數字的總和,在左側累加的同時,只要透過總和減去左側數字的總和,就能知道右側數字的總和,進而優化我們的演算法。
class Solution:
def waysToSplitArray(self, nums: List[int]) -> int:
left = 0
total = sum(nums)
valid = 0
for i in range(len(nums)-1):
left += nums[i]
right = total - left
if left >= right:
valid += 1
return valid