560. Subarray Sum Equals K
給定一個陣列,要找一個子陣列的總和為 K
。
暴力法
我想到的方法是我先算出每個位置的 prefix sum ,之後我就看如果當前這個位置的 prefix sum 減掉前面某一個位置的 prefix sum ,如果說當好等於 k
,就代表這兩個位置之間的總和是 k
,也就是說前一個位置到當前這個位置的子陣列的總和是 k
。
有一個邊角情況要考慮,那就是第一個元素可能剛好就是 k
,所以我們的 prefix_sum
陣列前面要多放一個零的元素。這樣剛好第一個元素就是一個子陣列滿足總和是 k
。
先從 [1..l]
算出 prefix sum 。
接著從 [i..l-1]
開始,設定起始位置,然後看看從 [i+1..l]
是不是有兩個位置之間的差剛好是 k
。
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = 0
l = len(nums)
prefix_sum = [0] * (l+1)
for i in range(1, l+1):
prefix_sum[i] = prefix_sum[i - 1] + nums[i - 1]
for i in range(l):
for j in range(i+1, l+1):
if prefix_sum[j] - prefix_sum[i] == k:
count += 1
return count
上面的方式,其實 cumulative_sum
在 外面的迴圈都是固定的。所以我們其實可以簡化成在外面的迴圈開始計算 prefix_sum
。這個方法理論上跟前一個方法的時間複雜度是相同的,但是 Python 在 LeetCode 裡面會超時,不知道為什麼
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = 0
l = len(nums)
for i in range(l):
prefix_sum = 0
for j in range(i, l):
prefix_sum += nums[j]
if prefix_sum == k:
count += 1
return count
Hash Table
這個方法比較特別一點,這個題目也是參考了兩個點
- 如果剛好計算到該位置的時候,總和為
k
,那就子陣列總和為 k 的情況加一 - 第二個情況和前面的情形有點像
- 上面的視角是:「當前的位置減去前面某個位置的差值是不是 k?」
- 這裡的視角是:「當前的位置減去
k
的差值,前面有沒有出現過?如果出現很多次,那就可以有組合出很多次的子陣列」例子:[1, 2, 3, -7, 1, 2, 3, -7, 7]
其中有兩個方法組合出 k 為 7 的子陣列 [1, 2, 3, -7, 1, 2, 3, -7, 7]
[1, 2, 3, -7, 7]
所以使用 Hash Table 的方式,是我每次到該位置時,更新完所有的數字後,我要去記錄每個 prefix sum 的次數有出現幾次。
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = 0
h = defaultdict(int)
# 先計算每個 prefix_sum 的次數
prefix_sum = 0
for num in nums:
prefix_sum += num
h[prefix_sum] = h[prefix_sum] + 1
# 1. 如果 prefix_sum 等於 k 計數加一
# 2. 加上 prefix_sum - k 的計數,
# 這裡不用 else 的情況是因為,如果前面有多次 prefix_sum 剛好是 0
# 那現在 prefix_sum 等於 k 的情況下,那些 prefix_sum 剛好是零的
# 陣列都可以組成不同的 sub array 。
prefix_sum = 0
for num in nums:
prefix_sum += num
if prefix_sum == k:
count += 1
count += h[prefix_sum - k]
return count
class Solution:
def subarraySum(self, nums: List[int], k: int) -> int:
count = 0
h = defaultdict(int)
cumulative_sum = 0
for num in nums:
cumulative_sum += num
if cumulative_sum == k:
count += 1
count += h[cumulative_sum - k]
h[cumulative_sum] = h[cumulative_sum] + 1
return count