Table of Contents:
🤔
相似的事物放一起,是讓環境井然有序的關鍵,這也是電腦世界中陣列(Array)此資料結構的設計理念。因為事物都在同處,我們可藉索引在常數時間(O(1)
)內找到對應元素(隨機存取)。
如果不是相似的事物,如果不放在一起,我們還有方法能好好整理它們嗎?可以,用鍵(Key)值(Value)架構即可。我們先定好一個雜湊(Hashing)函數,讓要管理的事物都依循此函數的判斷放到對應區塊中。這樣就能在常數時間(O(1)
)內找到鍵所對應的值。
以下為LeetCode中,與陣列(Array)和雜湊(Hashing)有關的題目與解答摘要。題目只會更多,但解題核心往往不變,祝大家都只練少量題目就在競試中有良好表現😊。
💡
- 有時反向遍歷陣列,做法會簡單很多
- 程式碼要一開始就簡潔很難,寫完再整理比較容易
- 善用陣列索引的有序性,有時會比雜湊表還好用
😎303. Range Sum Query – Immutable
Description
給予一個整數陣列nums
,請將其化為一種資料結構,能夠應對sumRange(left, right)
的要求(對於left ≤ right
,回傳此區間內的元素和)。
Example 1:
Input ["NumArray", "sumRange", "sumRange", "sumRange"] [[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]] Output [null, 1, -1, -3] Explanation NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]); numArray.sumRange(0, 2); // return (-2) + 0 + 3 = 1 numArray.sumRange(2, 5); // return 3 + (-5) + 2 + (-1) = -1 numArray.sumRange(0, 5); // return (-2) + 0 + 3 + (-5) + 2 + (-1) = -3
Solutions
Approach #1: Brute Force
我們可以直接遍歷區段內的元素並加總。
這樣的時間複雜度為O(N)
,空間複雜度為O(1)
。
class NumArray: def __init__(self, nums: List[int]): self.arr = nums def sumRange(self, left: int, right: int) -> int: res = 0 for i in range(left, right + 1): res += self.arr[i] return res
⭐Approach #2: Caching
若過程運算多次,紀錄先前算過的成果就能加快效能。但若儲存每個可能區間,空間複雜度會高達O(N2)
。我們可藉sumRange[i, j] = sumRange[0, j] - sumRange[0, i]
這概念,降低空間複雜度至O(N)
,
這樣的時間複雜度可達O(1)
,空間複雜度為O(N)
。
class NumArray: def __init__(self, nums): self.sum = [0] * (len(nums) + 1) for i in range(len(nums)): self.sum[i + 1] = self.sum[i] + nums[i] def sumRange(self, i, j): return self.sum[j + 1] - self.sum[i]
😐304. Range Sum Query 2D -Immutable
Description
給予一個二維陣列matrix
,請建構一個資料結構NumMatrix
,它的方法sumRegion
能求出範圍內的數總和。
Example 1:
Input ["NumMatrix", "sumRegion", "sumRegion", "sumRegion"] [[[[3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5]]], [2, 1, 4, 3], [1, 1, 2, 2], [1, 2, 2, 4]] Output [null, 8, 11, 12] Explanation NumMatrix numMatrix = new NumMatrix([[3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5]]); numMatrix.sumRegion(2, 1, 4, 3); // return 8 (i.e sum of the red rectangle) numMatrix.sumRegion(1, 1, 2, 2); // return 11 (i.e sum of the green rectangle) numMatrix.sumRegion(1, 2, 2, 4); // return 12 (i.e sum of the blue rectangle)
Solutions
❌Approach #1: Brute Force
我們可以直接計算,但在一些測試案例中會運算超時。
這樣的時間複雜度可達O(M*N)
,空間複雜度為O(1)
。
class NumMatrix: def __init__(self, matrix): self.data = matrix def sumRegion(self, row1, col1, row2, col2): total = 0 for r in range(row1, row2 + 1): for c in range(col1, col2 + 1): total += self.data[r][c] return total
⭐Approach #2: Caching Smarter
如同前題(No. 303),我們可在初始化時先儲存計算成果,減少日後運算。如何有效地儲存成果,我們以下圖的原點O([0, 0]
)、A([row1, col1]
)、B([row1, col2]
)、C([row2, col1]
)、D([row2, col2]
)點來說明:
- 算出整體面積
Sum(OD)
- 將整體面積減去
Sum(OB)
、Sum(OC)
,再加上Sum(OA)
,即為所求Sum(AD)
- 注意,記憶陣列
dp
的長寬各為原本大小再+1
,代表的是端點座標
這樣的時間複雜度為O(1)
,空間複雜度為O(M*N)
。
class NumMatrix: def __init__(self, matrix): if len(matrix) == 0 or len(matrix[0]) == 0: return self.dp = [[0] * (len(matrix[0]) + 1) for _ in range(len(matrix) + 1)] for r in range(len(matrix)): for c in range(len(matrix[0])): self.dp[r + 1][c + 1] = (self.dp[r + 1][c] + self.dp[r][c + 1] + matrix[r][c] - self.dp[r][c] ) def sumRegion(self, row1, col1, row2, col2): return ( self.dp[row2 + 1][col2 + 1] - self.dp[row1][col2 + 1] - self.dp[row2 + 1][col1] + self.dp[row1][col1] )
😐307. Range Sum Query – Mutable
Description
給予一個整數陣列nums
,請建構一個資料結構NumArray
,其方法:
update(index, val)
:將索引index
處的值更新為val
sumRange(left, right)
:回傳包含左右兩點的數和
Example 1:
Input ["NumArray", "sumRange", "update", "sumRange"] [[[1, 3, 5]], [0, 2], [1, 2], [0, 2]] Output [null, 9, null, 8] Explanation NumArray numArray = new NumArray([1, 3, 5]); numArray.sumRange(0, 2); // return 1 + 3 + 5 = 9 numArray.update(1, 2); // nums = [1, 2, 5] numArray.sumRange(0, 2); // return 1 + 2 + 5 = 8
Solutions
❌Approach #1: Naive
我們可以先直觀地處理,但這樣的解法在一些測試案例中會超時。
這樣的時間複雜度為O(N)
,空間複雜度為O(1)
。
class NumArray: def __init__(self, nums): self.nums = nums def sumRange(self, i, j): total = 0 for l in range(i, j + 1): total += self.nums[l] return total def update(self, i, val): self.nums[i] = val
⭐Approach #2: Segment Tree
此題適合使用線段樹(Segment Tree),它會把每個數做為一棵二元樹的葉子節點,依循其架構就能在O(logN)
內找到元素和或是修改資料。
這樣的時間複雜度為O(logN)
,空間複雜度為O(n)
。
class NumArray: # space: O(n) def __init__(self, nums: List[int]): if len(nums) > 0: self.n = len(nums) self.tree = [0] * (self.n * 2) self.buildTree(nums) # time: O(n) def buildTree(self, nums): for i in range(self.n, self.n * 2): self.tree[i] = nums[i - self.n] for i in range(self.n - 1, 0, -1): self.tree[i] = self.tree[i * 2] + self.tree[i * 2 + 1] def update(self, pos: int, val: int) -> None: pos += self.n self.tree[pos] = val while pos > 0: left = pos right = pos if pos % 2 == 0: right = pos + 1 else: left = pos - 1 # parent is updated after child is updated self.tree[pos // 2] = self.tree[left] + self.tree[right] pos //= 2 def sumRange(self, l: int, r: int) -> int: # get leaf with index 'l' and 'r' l += self.n r += self.n sum = 0 while l <= r: # if l is right child of its parent if l % 2 == 1: sum += self.tree[l] l += 1 # if r is left child of its parent if r % 2 == 0: sum += self.tree[r] r -= 1 l //= 2 r //= 2 return sum
😐347. Top K Frequent Elements
Description
給予一個整數陣列nums
和一個整數k
,請回傳陣列中出現頻率≥k
的元素。
Input: nums = [1,1,1,2,2,3], k = 2 Output: [1,2] Input: nums = [1], k = 1 Output: [1]
Solutions
Approach #1 使用堆積(Heap)
要求前K
項元素,我們通常會想到優先佇列(Prioirty Queue),也就是堆積(Heap)。我們:
- 將元素與出現次數建為一個雜湊表(
count
) - 用內建函式
heapq.nlargest()
,建立一個前K
大的陣列 - 回傳它即
這樣的時間複雜度為O(NlogK)
(僅排序前K
個),空間複雜度則為O(N+K)
(雜湊表O(N)
,堆積O(K)
)。
from collections import Counter import heapq class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: # O(1) time if k == len(nums): return nums # 1. build hash map : character and how often it appears # O(N) time count = Counter(nums) # 2-3. build heap of top k frequent elements and # convert it into an output array # O(N log k) time return heapq.nlargest(k, count.keys(), key=count.get)
⭐Approach #2 用陣列索引值分類出現次數不同的元素
我們可將陣列索引值當成歸類的鍵。我們:
- 用一個雜湊表
count
統計元素與其出現次數 - 創造一個列數
n+1
的二維陣列,將count
值依鍵放入索引值相同的陣列中 - 從尾端遍歷此陣列,將索引值
≥k
者納入res
這樣的時間和空間複雜度皆為O(n)
。
class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: count = {} freq = [[] for i in range(len(nums) + 1)] for n in nums: count[n] = 1 + count.get(n, 0) for n, c in count.items(): freq[c].append(n) res = [] for i in range(len(freq) - 1, 0, -1): for n in freq[i]: res.append(n) if len(res) == k: return res
😎392. Is Subsequence
Description
給予兩個字串s
和t
,如果s
是t
的子序列(subsequence )則回傳True
,否則回傳False
。
Example 1:
Input: s = "abc", t = "ahbgdc" Output: true
Example 2:
Input: s = "axc", t = "ahbgdc" Output: false
Solutions
⭐Approach #1: Two-Pointers
我們可以用Two-Pointers來解題:
- 用
l
和r
兩指標遍歷字串s
和t
- 若
s[l] == t[r]
,代表t
當下字元已符合,可讓r
往前, - 持續讓
r
往前,用下個字元判斷是否符合
- 若
- 遍歷完
s
或t
時,判斷l==len(s)
是否為真,看s
是否已比對完成
這樣的時間複雜度為O(|S|)
,空間複雜度為O(1)
。
class Solution: def isSubsequence(self, s: str, t: str) -> bool: l = 0 r = 0 while l < len(s) and r < len(t): if s[l] == t[r]: l += 1 r += 1 return l == len(s)
😐438. Find All Anagrams in a String
Description
給予兩字串s
和p
,請回傳在s
中所有能成為p
的異位構詞(anagram)之字串起始點索引為一陣列。
Example 1:
Input: s = "cbaebabacd", p = "abc" Output: [0,6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input: s = "abab", p = "ab" Output: [0,1,2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab".
Solutions
⭐Approach #1: Sliding Window
我們可先統計p
內的字元出現頻率,再用移動視窗判斷所夾擊的s
子字串,其字元出現頻率也相同。
這樣的時間複雜度為O(NS)
,空間複雜度為O(K)
。NS
為s
的長度,K
為出現過的元素數量。
class Solution: def findAnagrams(self, s: str, p: str) -> List[int]: l = 0 counterP = Counter(p) counterS = Counter(s[0:len(p) - 1]) res = [] for r in range(len(p) - 1, len(s)): counterS[s[r]] = counterS.get(s[r], 0) + 1 if counterP == counterS: res.append(l) l += 1 return res
😎485. Max Consecutive Ones
Description
給予一個二元陣列nums
,請回傳其中元素1
最大連續長。
Example 1:
Input: nums = [1,1,0,1,1,1] Output: 3 Explanation: The first two digits or the last three digits are consecutive 1s. The maximum number of consecutive 1s is 3.
Example 2:
Input: nums = [1,0,1,1,0,1] Output: 2
Solutions
⭐Approach #1: One pass
我們可以遍歷一次陣列,統計連續出現的最大長度。
這樣的時間複雜度為O(N)
,空間複雜度為O(1)
。
class Solution: def findMaxConsecutiveOnes(self, nums: List[int]) -> int: count = max_count = 0 for num in nums: if num == 1: count += 1 else: max_count = max(max_count, count) count = 0 return max(max_count, count)
😎448. Find All Numbers Disappeared in an Array
Description
給予一個具備n
個整數的陣列nums
,其數值界在[1, n]
內,請以一個陣列形式,回傳沒出現在此範圍內的數字。
Example 1:
Input: nums = [4,3,2,7,8,2,3,1] Output: [5,6]
Example 2:
Input: nums = [1,1] Output: [2]
Solutions
Approach #1: Using Hash Map
如果使用雜湊表,此題可以輕易地處理。
這樣的時間與空間複雜度皆為O(N)
。
class Solution(object): def findDisappearedNumbers(self, nums): hash_table = {} for num in nums: hash_table[num] = 1 result = [] for num in range(1, len(nums) + 1): if num not in hash_table: result.append(num) return result
⭐Approach #2: O(1) Space InPlace Modification Solution
若要讓空間複雜度降為O(1)
,我們得善用所給陣列,方法為:
- 以索引值作為數值範圍,但得注意索引值從
0
開始 - 遍歷陣列,將索引值對應數值變為負
- 再次遍歷陣列,若值
>0
代表沒出現過,加到陣列res
中 - 回傳
res
這樣的時間複雜度為O(N)
,空間複雜度為O(1)
。
class Solution: def findDisappearedNumbers(self, nums: List[int]) -> List[int]: for i in range(len(nums)): new_index = abs(nums[i]) - 1 if nums[new_index] > 0: # 代表出現過一次 nums[new_index] *= -1 result = [] for i in range(1, len(nums) + 1): # 代表沒出現過 if nums[i - 1] > 0: result.append(i) return result
😐487. Max Consecutive Ones II
Description
給予一個二元陣列nums
,若能反轉一次0
為1
,請回傳1
所能連續的最大長度。
Example 1:
Input: nums = [1,0,1,1,0] Output: 4 Explanation: - If we flip the first zero, nums becomes [1,1,1,1,0] and we have 4 consecutive ones. - If we flip the second zero, nums becomes [1,0,1,1,1] and we have 3 consecutive ones. The max number of consecutive ones is 4.
Example 2:
Input: nums = [1,0,1,1,0,1] Output: 4 Explanation: - If we flip the first zero, nums becomes [1,1,1,1,0,1] and we have 4 consecutive ones. - If we flip the second zero, nums becomes [1,0,1,1,1,1] and we have 4 consecutive ones. The max number of consecutive ones is 4.
Solutions
⭐Approach #1: Sliding Window
我們可以用移動視窗來解題:
- 用指標
l
和r
當作窗口邊界,zeroCount
記錄窗口內的0
數量,res
記錄最大長度 - 用
r
遍歷陣列:- 若遇到
0
,將zeroCount+1
- 若
zeroCount>1
,就持續移動l
,直到zeroCount<2
- 更新
res
- 若遇到
- 遍歷完後,
res
即為所求
這樣的時間複雜度為O(N)
,空間複雜度為O(1)
。
from typing import List class Solution: def findMaxConsecutiveOnes(self, nums: List[int]) -> int: res = 0 l, r = 0, 0 zeroCount = 0 while r < len(nums): if nums[r] == 0: zeroCount += 1 while zeroCount > 1: if nums[l] == 0: zeroCount -= 1 l += 1 res = max(res, r - l + 1) r += 1 return res
😎496. Next Greater Element I
Description
陣列某元素x
的下個更大元素(next greater element),是指其右邊比它更大的首個元素。現在給予兩個0-indexed的整數陣列nums1
和nums2
,前者為後者的子集合(subset)。
現在遍歷nums1
,找出兩陣列同值時(兩陣列內的值皆相異)的nums2
索引和其下個更大元素,沒有則回傳-1
。請回傳等同nums1
長度的答案陣列。
Example 1:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2] Output: [-1,3,-1] Explanation: The next greater element for each value of nums1 is as follows: - 4 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1. - 1 is underlined in nums2 = [1,3,4,2]. The next greater element is 3. - 2 is underlined in nums2 = [1,3,4,2]. There is no next greater element, so the answer is -1.
Example 2:
Input: nums1 = [2,4], nums2 = [1,2,3,4] Output: [3,-1] Explanation: The next greater element for each value of nums1 is as follows: - 2 is underlined in nums2 = [1,2,3,4]. The next greater element is 3. - 4 is underlined in nums2 = [1,2,3,4]. There is no next greater element, so the answer is -1.
Solutions
以下所用符號,m
為nums1
的元素量,n
為nums2
的元素量,n > m
。
Approach #1: Brute Force
我們可以先直觀地處理。
這樣的時間複雜度為O(m*n)
,空間複雜度為O(1)
。
class Solution: def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: res = [] for n in nums1: j = 0 while nums2[j] != n: j += 1 while j < len(nums2) and nums2[j] <= n: j += 1 if j == len(nums2): res.append(-1) else: res.append(nums2[j]) return res
⭐Approach #2: Using Stack
若先算出nums2
各元素的下個更大元素,我們就能將時間複雜度降至O(n)
:
- 用堆疊
stack
輔助找出nums2
各元素的下個更大元素,雜湊表mp
儲存 - 遍歷
nums2
- 將元素存入
stack
- 若當前元素
>
先前元素,則為先前元素的下個更大元素,將關係記錄到mp
中
- 將元素存入
- 遍歷
nums1
,用陣列res
儲存各元素的下個更大元素 - 回傳
res
,即為所求
這樣的時間與空間複雜度皆為O(n)
。
from typing import List class Solution: def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: # 輔助找出nums2中各元素的下個更大元素 stack = [] # 儲存每個元素的下個更大元素 mp = {} for num in nums2: # 找到之前所存元素的下個更大元素 while stack and num > stack[-1]: # 記錄元素的下個更大元素,並將其從堆疊中移除 mp[stack.pop()] = num stack.append(num) # 此時堆疊內的元素皆沒有下個更大元素 while stack: mp[stack.pop()] = -1 # 使用nums1的元素順序,放入對應答案 res = [] for num in nums1: res.append(mp[num]) return res
😐523. Continuous Subarray Sum
Description
給予一整數陣列nums
和整數k
,請判斷nums
是否有好(good)的子陣列。好的特徵是:
- 長度
≥2
- 子陣列的元素和是
k
的倍數(0
也算)
Example 1:
Input: nums = [23,2,4,6,7], k = 6 Output: true Explanation: [2, 4] is a continuous subarray of size 2 whose elements sum up to 6.
Example 2:
Input: nums = [23,2,6,4,7], k = 6 Output: true Explanation: [23, 2, 6, 4, 7] is an continuous subarray of size 5 whose elements sum up to 42. 42 is a multiple of 6 because 42 = 7 * 6 and 7 is an integer.
Example 3:
Input: nums = [23,2,6,4,7], k = 13 Output: false
Solutions
⭐Approach #1: HashMap
此題需要的主要觀念是對餘數的了解:
- 使用雜湊表
mp
,記錄在索引元素當下總和(total
)的餘數 - 遍歷陣列
nums
,若餘數值再次出現,代表這中間有子陣列的元素和可被k
整除
這樣的時間複雜度為O(N)
,空間複雜度為O(min(N, k))
,N
為元素數量。
class Solution: def checkSubarraySum(self, nums: List[int], k: int) -> bool: # 如果0再次出現,那可確保即便是前兩個元素也滿足後面的判斷式 mp = {0: -1} total = 0 for i, j in enumerate(nums): total += j remainder = total % k # 若再度出現相同餘數,代表中間有個子陣列的和為k的倍數 if remainder in mp: # 確認此子陣列相隔超過2 if i - mp[remainder] >= 2: return True else: continue mp[remainder] = i return False
😐535. Encode and Decode TinyURL
Description
短網址服務(TinyURL)能將一個長網址(e.g. https://leetcode.com/problems/design-tinyurl
)轉換成短網址(e.g. http://tinyurl.com/4e9iAk
),請設計一個類別來完成此功能。
Example 1:
Input: url = "https://leetcode.com/problems/design-tinyurl" Output: "https://leetcode.com/problems/design-tinyurl" Explanation: Solution obj = new Solution(); string tiny = obj.encode(url); // returns the encoded tiny url. string ans = obj.decode(tiny); // returns the original url after decoding it.
Solutions
⭐Approach #1 Using Simple Counter
轉換長網址為短網址的關鍵在於一對一映射,我們使用遞增數字來完成。
class Codec: def __init__(self): self.encodeMap = {} self.decodeMap = {} self.base = "http://tinyurl.com/" def encode(self, longUrl: str) -> str: if longUrl not in self.encodeMap: # 用遞增數字為編號 shortUrl = self.base + str(len(self.encodeMap) + 1) self.encodeMap[longUrl] = shortUrl self.decodeMap[shortUrl] = longUrl return self.encodeMap[longUrl] def decode(self, shortUrl: str) -> str: return self.decodeMap[shortUrl]
😐554. Brick Wall
Description
在你面前有面n
列矩形牆,我們以二維陣列wall
表達裡面磚頭的寬度(高度皆相同),每列總寬度皆同。
請從頂到尾劃一條垂直線,請回傳可以劃過最少塊的磚頭數量(擦邊狀態不需計算)。
Example 1:
Input: wall = [[1,2,2,1],[3,1,2],[1,3,2],[2,4],[3,1,2],[1,3,1,1]] Output: 2
Example 2:
Input: wall = [[1],[1],[1]] Output: 3
Solutions
Approach #1 HashMap
我們可用個雜湊表,記錄每個x
座標所沒切到的磚頭數。遍歷完後就能知道哪個座標所切到的磚頭數最少。
這樣的時間複雜度為O(n)
,空間複雜度為O(m)
,n
為牆內磚頭總數,m
為牆寬。
from collections import defaultdict class Solution: def leastBricks(self, wall): map = defaultdict(int) for bricks in wall: # 磚頭間隙的座標 xCord = 0 for i in range(len(bricks) - 1): xCord += bricks[i] map[xCord] += 1 # 以每層都會切到來更新 res = len(wall) for key in map: res = min(res, len(wall) - map[key]) return res
😐560. Subarray Sum Equals K
Description
給予一個整數陣列nums
和一個整數k
,請回傳和為k
的子陣列數量。
Example 1:
Input: nums = [1,1,1], k = 2 Output: 2
Example 2:
Input: nums = [1,2,3], k = 3 Output: 2
Solutions
❌Approach #1: Brute Force
我們可以直觀找出所有子陣列後,判斷和是否為k
。
這樣的時間複雜度為O(N3)
,空間複雜度為O(1)
。
class Solution: def subarraySum(self, nums, k): count = 0 for start in range(len(nums)): for end in range(start + 1, len(nums) + 1): total = sum(nums[start:end]) if total == k: count += 1 return count
❌Approach #2: Without Space
我們也可以遍歷並讓每個元素作為子陣列起點來判斷。
這樣的時間複雜度為O(N2)
,空間複雜度為O(1)
。
class Solution: def subarraySum(self, nums, k): count = 0 for start in range(len(nums)): total = 0 for end in range(start, len(nums)): total += nums[end] if total == k: count += 1 return count
⭐Approach #3: Using Hashmap
子陣列是一段位置連續的元素,若記錄每段和,就能在遍歷一趟後完成所求:
- 用
count
紀錄所求子陣列數量,total
紀錄元素和,hashmap
紀錄和值與出現次數 - 遍歷陣列
nums
:- 更新
total
- 若
total - k
已出現過(首次對到的為0
,即total = k
,後續對到的則會是k
的倍數),則將出現次數加到count
中
- 更新
- 遍歷完時,
count
即為所求
這樣的時間複雜度為O(N)
,空間複雜度為O(N)
。
class Solution: def subarraySum(self, nums, k): count = 0 total = 0 hashmap = {0: 1} for i in range(len(nums)): total += nums[i] if total - k in hashmap: count += hashmap[total - k] hashmap[total] = hashmap.get(total, 0) + 1 return count