11/2020 Flashcards

1
Q
5.Longest Palindromic Substring
Given a string s, return the longest palindromic substring in s.
Input: s = "babad"
Output: "bab"
Note: "aba" is also a valid answer.
A

Brute Force
Pick all possible starting and ending positions for a substring, and verify if it is a palindrome.
Time: O(n3); Space: O(1)

Expand Around Center
A palindrome can be expanded from its center, and there are only 2n - 1 such centers (长度奇/偶)
Time: O(n2); O(n) for each center; Space: O(1)
class Solution:
def longestPalindrome(self, s: str) -> str:
result = “”
for i in range(len(s)):
tmp = self.findlongest(s,i,i+1) # ‘baab’
if len(tmp)>len(result): result = tmp
tmp = self.findlongest(s,i,i) # ‘aba’
if len(tmp)>len(result): result = tmp
return result
def findlongest(self,s, l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1; r += 1
return s[l+1:r]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

200.Number of Islands

Given anm x n2dgridmap of’1’s (land) and’0’s (water), returnthe number of islands.

A
Recursive (DFS)
Linear scan grid,直到找到’1’,对该元素进行DFS
During DFS: 将当前元素变为’0’, 继续DFS其周边为’1’的元素
Time: O(mn)
Space: worst caseO(mn)

(*) 也可以通过Stack实现DFS / Queue实现BFS

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
  1. Moving Average from Data Stream
    Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window.

MovingAverage m = new MovingAverage(3);

m. next(1) = 1
m. next(10) = (1 + 10) / 2
m. next(3) = (1 + 10 + 3) / 3
m. next(5) = (10 + 3 + 5) / 3

A

Class variables:

  • self.queue => to store the values from the data stream,
  • self.n => for the size of the moving window;

Solution 1: Array or List
We first append the value to the queue. We then retrieve the last n values from the queue, in order to calculate the average.
for list-based solution with retrieving last n elements without poping the first:
for each invocation of next(val)
- - Time O(n) with n = window size, since we need to retrieve N elements from the queue at each invocation of next(val) function. (array/list有index,取任一元素的complexity为O(1), N各元素complexity为O(N))
- - Memory O(M) with M = number of elements in data stream (continuosly growing)

Solution 2:
for deque-based solution with poping the first element:
- - constant time complexity O(1) as we don’t shift all the elements while popping
- memory O(n)
notes: len() has complexity O(1)
不用list.pop(0)因为list when pop(0), copies all elements and moves them on the left for 1 element, very heavy operation in terms of time-complexity;

如果用arraylist储存整个数据流,加上两个变量window_sum和tail,似乎也可以达到time O(1), 但spaceO(M);

若使用arraylist但每次pop(0),则time为O(N),因为每次都要平移所有elements

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
  1. Group Anagrams
    Given an array of strings strs, group the anagrams together. You can return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

Input: strs = [“eat”,”tea”,”tan”,”ate”,”nat”,”bat”]
Output: [[“bat”],[“nat”,”tan”],[“ate”,”eat”,”tea”]]

A

hash table with keys == transformed words

sorted(word) outputs list, use’‘.join(sorted(word)) to return str
或者用tuple(sorted(word))做d.keys: tuple is hashable, but list not

N is the length of strs, K is the maximum length of a string in strs
- hash table with sorted strings as keys:
time : O(NKlogK) = O(N) loop over input * O(KlogK) to sort each word
memo: O(NK)
- counter solution:
time: O(NK)
memo: O(NK)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
  1. Ransom Note
    Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.

Each letter in the magazine string can only be used once in your ransom note.

Input: ransomNote = “aa”, magazine = “ab”
Output: false

A
  • hash table of all available letters from magazine (manually or through collections.Counter);
  • then iterate through ransom note and substract counter values from hash table if found.
  • return False if one of dict values turns to negative or if item from ransom note is not found in magazine keys

m length of magazine, n length of ransom note.
k number of unique characters across ransom note and magazine
Time Complexity : O(m)
code,复杂度为O(m)+O(n),
当m O(m)
当m>n, O(m)+O(n) < O(2m) => O(m)
Space : O(k) (或 O(1) 因为k<26可以当作constant).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
  1. Two Sum
    Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

You can return the answer in any order.

A

=> hash table {element: index} iterate over k,v: if k == target - k -> return val

time: O(n)
memo: O(n)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Project Euler #67: Maximum path sum II

By starting at the top of the triangle below and moving to adjacent numbers on the row below, Find the maximum total from top to bottom of the triangle given in input.

A

dynamic programming from bottom to top :
Sum each 2 lines looping over shorter line and adding to each element max(2 children).

! convert from str() to int()

def maxPathSum(triangle, numRow):
    for i in range(numRow-2, -1, -1): 
        for j in range(i+1):
            triangle[i][j] = max(triangle[i][j]+ triangle[i+1][j], triangle[i][j]+triangle[i+1][j+1])
    return triangle[0][0]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q
  1. Shuffle an Array

Given an integer array nums, design an algorithm to randomly shuffle the array.

Implement the Solution class:

Solution(int[] nums) Initializes the object with the integer array nums.
int[] reset() Resets the array to its original configuration and returns it.
int[] shuffle() Returns a random shuffling of the array.

A
class Solution:
    def \_\_init\_\_(self, nums):
        self.array = nums
        self.original = list(nums)
    def reset(self):
        self.array = self.original
        self.original = list(self.original)
        return self.array
    def shuffle(self):
        aux = list(self.array)
    for idx in range(len(self.array)):
        remove_idx = random.randrange(len(aux))
        self.array[idx] = aux.pop(remove_idx)

    return self.array
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q
  1. Search in Rotated Sorted Array
    You are given an integer array nums sorted in ascending order, and an integer target.

Suppose that nums is rotated at some pivot unknown to you beforehand (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

If target is found in the array return its index, otherwise, return -1.

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

A

所以直接用二分,O(lg(n))

  • 如果是mid,return mid
  • 如果mid在绿色线上,就对绿色线进行二分
  • 如果mid在红色线上,就对红色线进行二分
  • 都没找到,return -1
绿色线 / 红色线
# compare nums[mid] with nums[start] => figure out on with branch 
# NOT nums[mid] with target!!!!
对每条线二分时,别忘记对nums[start] 和nums[end]取等号
if nums[mid] > target >= nums[start] 
if nums[mid] < target <= nums[end]
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        start, end = 0, len(nums)-1
        while start + 1 < end: # like this when ends, start is always NEXT TO end
            mid = (start + end) // 2
            if nums[mid] == target:
                return mid
            if nums[mid] > nums[start]:
                if nums[mid] > target >= nums[start]  :
                    end = mid 
                else:
                    start = mid
            else: 
                if nums[mid] < target <= nums[end] :
                    start = mid
                else: 
                    end = mid
    if nums[start]==target:
        return start
    if nums[end]==target:
        return end 

    return -1
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q
  1. Intersection of Two Arrays
    Given two arrays, write a function to compute their intersection.

Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2]

A

N length of nums1, M length of nums2
NAIVE: iterate along the first array nums1 and to check for each value if this value in nums2
O(n×m) time complexity

SOLUTION 1 : convert both arrays into sets; iterate over the smallest set checking the presence of each element in the larger set
Time :O(n+m), O(n) convert nums1 into set, O(m) convert nums2, and contains/in operations are O(1) in the average case.
Space: O(m+n) in the worst case when all elements in the arrays are different.

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        s1, s2 = set(nums1), set(nums2)
        return list(s1 &amp; s2)

SOLUTION 2: sort the two list, and use two pointer to search in the lists to find common elements.

    nums1.sort()
    nums2.sort()
    i = 0
    j = 0
    res = []
    while i < len(nums1) and j < len(nums2):
        if nums1[i] < nums2[j]:
            i += 1
        elif nums1[i] > nums2[j]:
            j += 1
        else:
            same = nums1[i]
            # when we find equal element
            res.append(same)
            while i < len(nums1) and nums1[i] == same:
                i += 1
            while j < len(nums2) and nums2[j] == same:
                j += 1
    return res
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q
  1. Kth Smallest Element in a Sorted Matrix
    Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct element.

matrix = [
   [ 1,  5,  9],
   [10, 11, 13],
   [12, 13, 15]
],
k = 8,

return 13.

A

Approach 0: flatten the matrix
n: number of elements in matrix
Time: flatten O(n), sort O(nLogn) => O(nLogn)
Space: O(n)

class Solution:
    def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
        flat = sorted([x for row in matrix for x in row])
        return flat[k-1]

Approach 1: Min-Heap approach

1) Considering each row (or column) an individual list.
2) Take the first element of min(N, K) rows where N represents the number of rows, and add each of these elements (value, row, column) to the min-heap.
3) At each step, remove the minimum element from the heap. The element will tell us which row should be further consumed. ( If the current minimum element was from row r and had a column position c, then the next element to be added to the heap will be (r, c+1))
Loop until we iterate over K elements.

Time: let X=min(K,N), complexity X+Klog(X)
Building a min-heap which takes O(X) time
Heapify K times which takes O( KLogX) time.
Space : O(K), as the Min-Heap stores one row at a time.

import heapq
class Solution:
    def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
        N = len(matrix)
        minHeap = []
        for r in range(min(k, N)):
            # We add triplets of information for each cell
            minHeap.append((matrix[r][0], r, 0))
    heapq.heapify(minHeap)    

    while k:
        element, r, c = heapq.heappop(minHeap)
        if c < N - 1:
            heapq.heappush(minHeap, (matrix[r][c+1], r, c+1))
        k -= 1

    return element
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q
  1. Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.

Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

Follow up: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.

A

Greedy
- curSum 初始值为0,每遍历一个数字 num,比较 - curSum + num 和 num 中的较大值存入 curSum
然后再把 maxSum 和 curSum 中的较大值存入 maxSum

Time: O(n), Space: O(1)

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        cumsum, maxsum = 0, -float(inf)
        for i in range(n):
            cumsum = max(nums[i], nums[i]+cumsum)
            maxsum = max(maxsum, cumsum)
        return maxsum
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

21.Merge Two Sorted Lists
Merge two sorted linked lists and return it as a newsortedlist. The new list should be made by splicing together the nodes of the first two lists.

A
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        tmp = ListNode(0)
        cur = tmp
        while l1 and l2:
            if l1.val <= l2.val:
                cur.next = l1
                l1 = l1.next
            else:
                cur.next = l2
                l2 = l2.next
            cur = cur.next
        if l1: 
            cur.next = l1
        if l2:
            cur.next = l2
        return tmp.next
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

20.Valid Parentheses

Given a stringscontaining just the characters’(‘,’)’,’{‘,’}’,’[‘and’]’, determine if the input string is valid.

A

Approach 1: Stacks
# In the end, the stack should be empty
Time: O(n)
Space: O(n)

class Solution:
    def isValid(self, s: str) -> bool:
        d = {'(':')','{':'}','[':']'}
        stack = []
        for x in s:
            if x in d.keys():
                stack.append(x)
            else:
                if not stack:
                    return False
                tmp = stack.pop()
                if x != d[tmp]:
                    return False
        # In the end, the stack should be empty
        if not stack:        
            return True
        return False
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

121.Best Time to Buy and Sell Stock
Say you have an array for which theithelement is the price of a given stock on dayi.
If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.

A

找到此前中最小的一个与当前相减,之后取最大的差值
Time: O(n)
Space: O(1)

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        pmin = prices[0]
        globmax = 0
        for p in prices:
            if p
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q
  1. Reorder Data in Log Files
    For each log, the first word in each log is an alphanumeric identifier. Then, either:
    - Each word after the identifier will consist only of lowercase letters, or;
    - Each word after the identifier will consist only of digits.

We will call these two varieties of logs letter-logs and digit-logs. It is guaranteed that each log has at least one word after its identifier.

Reorder the logs so that all of the letter-logs come before any digit-log. The letter-logs are ordered lexicographically ignoring identifier, with the identifier used in case of ties. The digit-logs should be put in their original order.

Return the final order of the logs.

Input: logs = [“dig1 8 1 5 1”,”let1 art can”,”dig2 3 6”,”let2 own kit dig”,”let3 art zero”]
Output: [“let1 art can”,”let3 art zero”,”let2 own kit dig”,”dig1 8 1 5 1”,”dig2 3 6”]

A

Custom sorting with key
define a function to label the item in logs with 0 if the rest is alphabet, with 1 if the rest is number.
sort the list according to the label.

class Solution:
    def reorderLogFiles(self, logs: List[str]) -> List[str]:
        def f(log):
            id_, rest = log.split(" ", 1)
            return (0, rest, id_) if rest[0].isalpha() else (1,)
    return sorted(logs, key = f)
17
Q

953.Verifying an Alien Dictionary
In an alien language, surprisingly they also use english lowercase letters, but possibly in a different order. The order of the alphabet is some permutation of lowercase letters.

Given a sequence of words written in the alien language, and the order of the alphabet, return true if and only if the given words are sorted lexicographicaly in this alien language.

Input: words = [“word”,”world”,”row”], order = “worldabcefghijkmnpqstuvxyz”
Output: false
Explanation: As ‘d’ comes after ‘l’ in this language, then words[0] > words[1], hence the sequence is unsorted.

A

用customized sorting function

class Solution:
    def isAlienSorted(self, words: List[str], order: str) -> bool:
        d = dict()
        for i, letter in enumerate(order):
            d[letter] = i
        def f(word):
            return tuple(d[w] for w in word)
    return words == sorted(words, key = f)
18
Q
  1. Reverse Linked List
    Reverse a singly linked list.

Example:

Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
Follow up:

A linked list can be reversed either iteratively or recursively. Could you implement both?

A
Iterative 迭代
重点:用三个指针,分别指向prev,cur 和 nxt
# 新建prev为None, cur为head
# 当cur不为None,重复:
        #   - 用next追踪cur.next
        #   - 更改cur使之指向prev
        #   - prev和cur后移,分别成为cur和next
Time: O(N)
Space: O(1)
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        prev = None
        cur = head
        while cur:
            nxt = cur.next
            cur.next = prev
            prev = cur
            cur = nxt
        return prev

Recursive(难懂。。)
(=>递归类似使用stack, Space O(N))

19
Q
  1. Palindrome Linked List
    Given a singly linked list, determine if it is a palindrome.

Example 1:

Input: 1->2
Output: false
Example 2:

Input: 1->2->2->1
Output: true
Follow up:
Could you do it in O(n) time and O(1) space?

A

Idea 1: (Time O(N), Space O(N) )Copy into Array List and then Use Two Pointer Technique (compare indexes at either end, moving in towards the middle).

Idea 2.0: (Time O(N), Space O(N))用快慢指针找到中间点,前半段边遍历边放入stack;找到中间点后,慢指针每向前一步,与stack.pop()的node比较,如果一样ok继续,不一样则返回False

§快慢指针条件:while (fast.next) and (fast.next.next)
§判断长度奇/偶: if even -> 结束时 fast.next exists

Idea 2.1 Reverse Second Half In-place 
Time O(N), Space O(1)

*特殊情况: head is None=> return True

20
Q
  1. Longest Substring Without Repeating Characters
    Given a string s, find the length of the longest substring without repeating characters.

Input: s = “abcabcbb”
Output: 3
Explanation: The answer is “abc”, with the length of 3.

A

-Brute force: O(n3)

- Sliding window: for each index i, find the maximum size of substrings without duplicate characters start with indexi. 
Time O(2n) = O(n) In the worst case each character will be visited twice byiandj.
  • Sliding Window Optimized
    Instead of using a set to tell if a character exists or not, we could define a mapping of the characters to its index. Then we can skip the characters immediately when we found a repeated character.
21
Q
  1. Longest Valid Parentheses
    Given a string containing just the characters ‘(‘ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.
    Input: s = “)()())”
    Output: 4
A

【Using Stack: time O(n), space O(n)】
初始化 start=-1,stack=[], maxlen=0
遍历 string,
- 当s[i]为’(‘, 压入stack
- 当s[i]为’)’,
-> 若当前stack为空,则不可能valid => 重新赋值start = i;
-> 否则,stack.pop(), 即组成一个valid parenthese
- 若pop后stack为空: maxlen = max(maxlen, i-start)
- 否则:maxlen = max(maxlen, i-stack[-1]), 有可能继续有valid

Brute force: Time O(n3) 【列举是 O(n²),判断是否合法是 O(n)】; Space O(n)
列举所有的字符串,然后判断每个字符串是不是符合(使用valid parenthese中stack的方法)

Brute force ++: Time O(n2), Space O(1)
不用栈,用一个变量,因为只有一种括号, 遇到’(‘加 1,’)’减 1. 若为 0 ,更新maxlen

KO: expand from center (like longest palindrome ): cuz not necessarily symmetric # eg: “()(())”

22
Q
  1. Merge Intervals
    Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
    Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
    Output: [[1,6],[8,10],[15,18]]
A
Time: O(nlogn) = sort O(nlogn) + merge O(n), 
Space O(N)

以 start 的值从小到大给区间排序,首先把第一个区间存入结果中,然后从第二个开始遍历区间集,

  • 如果结果中最后一个区间和遍历的当前区间无重叠,直接将当前区间存入结果中
  • 如果有重叠,将结果中最后一个区间的 end 值更新为结果中最后一个区间的 end 和当前 end 值之中的较大值

class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort()
ans = [intervals[0]]
for current in intervals[1:]:
if current[0]>ans[-1][1]: # current start > previous end: new interval
ans.append(current)
else:
ans[-1][1] = max(ans[-1][1], current[1])
return ans

23
Q

238.Product of Array Except Self
Array
Given an arraynumsofnintegers wheren> 1, return an arrayoutputsuch thatoutput[i]is equal to the product of all the elements ofnumsexceptnums[i].

Note: Please solve it without division and in O(n).

A

题目要求不能使用除法

Approach 1: Left and Right product lists
Time: O(3n) = O(n), Space: O(n)

def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)
        L, R = [0]*n, [0]*n
        # left product list
        L[0] = 1
        for i in range(1,n):
            L[i] = nums[i-1] * L[i-1]
        # right product list
        R[-1] = 1
        for i in range(n-2, -1, -1):
            R[i] = nums[i+1] * R[i+1]
        # calculate product of two lists
        return [l*r for (l,r) in zip(L, R)]

Approach 2: O(1) space approach
(doesn’t count the output array) Use the output array as one of L or R and construct the other one on the fly.

    ans = [0]*n
    ans[0] = 1
    for i in range(1,n):
        ans[i] = nums[i-1] * ans[i-1]

    prod = 1
    for i in range(n-2, -1, -1):
        prod = prod * nums[i+1]
        ans[i] = ans[i]*prod
24
Q
  1. Number of Connected Components in an Undirected Graph

Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to find the number of connected components in an undirected graph.

Example 1:

Input: n = 5 and edges = [[0, 1], [1, 2], [3, 4]]

 0          3
 |            |
 1 --- 2    4 

Output: 2

A

DFS, time O(V + E)
1) 对每个node建一个visit map,一个edgemap(node: [相node 1, 相连node 2, … ])
2) 初始化count为0;对每个尚未visited的node进行dfs; 而后count++
3) dfs:将当前node设为visited; 对edgemap中与之相连且尚未visit的node继续dfs

    def countComponents(self, n: int, edges: List[List[int]]):
        visit = dict()
        for node in range(n):
            visit[node] = 0
    mapedge = collections.defaultdict(set)
    for ed in edges:
        mapedge[ed[0]].add(ed[1])
        mapedge[ed[1]].add(ed[0])
        count = 0 
        for node in visit.keys():
            # if not visited yet
            if visit[node]==0:
                self.dfs(node, visit, mapedge)
                count += 1
        return count
    def dfs(self, node, visit, mapedge):
        visit[node] = 1
        for x in mapedge[node]:
            if visit[x]==0:
                self.dfs(x, visit, mapedge)
25
Q
  1. Subarray Sum Equals K

Given an array of integers nums and an integer k, return the total number of continuous subarrays whose sum equals to k.

Input: nums = [1,1,1], k = 2
Output: 2

Constraints:
1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000 可以为负数!
-107 <= k <= 107

A
1)Brute force: 
	time O(n3) = all subarrays O(n2) * sum of each subarray O(n); 
	space O(1)
2)Cumulative Sum:  计算到每个元素的cumsum -> nums[i:j]之和就等于cumsum[j]-cumsum[i]
	time O(n2) = create cumsum O(n) +  all subarrays O(n2) * subtraction O(1) , 
	space O(n)
def subarraySum(self, nums: List[int], k: int) -> int:
    n = len(nums)
    cumsum = [0] * (n+1)
    count = 0
    for i in range(1, n+1):
        cumsum[i] = nums[i-1] + cumsum[i-1]
    for i in range(n):
        for j in range(i+1, n+1):
            if cumsum[j] - cumsum[i] == k:
                count += 1
    return count
3) PrefixSum + Hashmap: time O(n), space O(n)
    def subarraySum(self, nums: List[int], k: int) -> int:
        countMap = dict()
        count = 0
        prefixSum = 0
        # init countMap
        countMap[0] = 1
    # go through each element
    for ele in nums:
        prefixSum += ele
        # how many previous sum has value "prefixSum-k"
        count += countMap.get(prefixSum-k, 0)
        # update map
        countMap[prefixSum] = countMap.get(prefixSum, 0) + 1

    return count