題目連結:
題目意譯:
給定一陣列 nums 以及一整數 target 。
回傳最大的非空且不重疊子陣列之數量,使得每個子陣列中的值總和等於 target 。
限制:
1 ≦ nums.length ≦ 10 ^ 5
-10 ^ 4 ≦ nums[i] ≦ 10 ^ 4
0 ≦ target ≦ 10 ^ 6
範例測資:
範例 1:
輸入: nums = [1,1,1,1,1], target = 2
輸出: 2
解釋: 其有著 2 個不重疊的子陣列於 [1,1,1,1,1] 其總和值等於 target(2)。
範例 2:
輸入: nums = [-1,3,5,1,4,2,-9], target = 6
輸出: 2
解釋: 其有著 3 個子陣列有著總和值等於 6 。
([5,1], [4,2], [3,5,1,4,2,-9]) 但只有前兩個沒有重疊。
範例 3:
輸入: nums = [-2,6,6,3,5,4,1,2,8], target = 10
輸出: 3
範例 4:
輸入: nums = [0,0,0], target = 0
輸出: 3
解題思維:
(以下為了方便起見,把 nums 的索引值設為從 1 開始)
先利用前綴和(Prefix Sums,如
這題)的概念得到一陣列 P。其中 P[0] = 0 、 P[i] = nums[1] + …… nums[i] = P[i - 1] + nums[i] (i > 0)
接著我們掃過陣列 nums 。當我們現在是在 nums[i] 時,如果 P[0] ~ P[i - 1] 存在 P[i] - target 時(假設其為 P[j] ,注意可能會有多個,不過其實只要考慮較靠近 i 的即可(等等會看到原因)),也就表示 P[i] - P[j] = target 。因此,此時我們便找到了一個區間 [j + 1, i] 其總和為 target 。
因此掃完 nums 之後我便可以得到所有的總和等於 target 之子陣列。例如範例 2 的 nums = [-1,3,5,1,4,2,-9] 、 target = 6 ,掃完之後我們得
[3, 4] 、 [5, 6] 、 [2, 7]
這三個區間,而它們依序對應著
[5,1] 、 [4,2] 、 [3,5,1,4,2,-9]
這三個子陣列。
因此我們可以看到現在問題變成了:要怎樣才能盡可能地挑越多越好,使得這些子陣列彼此皆不重疊?而這個問題可以參見
這題的作法——對每個區間的右端點排序,然後貪心地去取與先前區間不重疊的區間即可(因此剛剛有多個 P[j] 時的情況,我們基本上只會取到最右側的(因為我們是從 nums 頭掃到尾))。
所以最後取的區間數量即是所求。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。