int pos = (n - 1) & hash
), so
this op can be O(1) time complexity. (find bucket address directly, NO
need to loop over all items)Continous sum
Pair of sums
Sub array sum
TODO : note this as pattern!!!
prefix sum
+ hashmap ``` subarray[i,j] = prefixSum[j] -
prefixSum[i-1]so, to find a subarray equals k
-> prefixSum[j] - prefixSum[i-1] = k
-> prefixSum[j] - k = prefixSum[i-1]
-> so all need to do is : check if “prefixSum[j] - k” is in map ```
check permutaion sub string
// LC 567
// ...
/** NOTE !!!
*
* we use below trick to
*
* -> 1) check if `new reached s2 val` is in s1 map
* -> 2) check if 2 map are equal
*
* -> so we have more simple code, and clean logic
*/
if (map2.equals(map1)) {
return true;
}
// ...
letest existed idx
Definition
When to use
sum, pair, continuous
When Not to use
Hash Collisions
Ref
get
: get value from dict with default value if key not
existed10]: d = {'a': 1, 'b': 2}
In ['a']
...: d[10]: 1
Out[
11]: d.get('a')
In [11]: 1
Out[
12]: d.get('c', 0)
In [12]: 0
Out[
13]: d.get('z')
In [
14]: In [
setdefault()
d.setdefault(new_key) d.setdefault(new_key, new_value)
car = { “brand”: “Ford”, “model”: “Mustang”, “year”: 1964 }
car.setdefault(“my_key”) print (car) # In [18]: car # Out[18]: {‘brand’: ‘Ford’, ‘model’: ‘Mustang’, ‘year’: 1964, ‘my_key’: None}
car.setdefault(“color”, “white”) print (car) # Out[22]: # {‘brand’: ‘Ford’, # ‘model’: ‘Mustang’, # ‘year’: 1964, # ‘my_key’: None, # ‘color’: ‘white’}
- `Sort` on ***hashmap (dict)***
```python
# https://stackoverflow.com/questions/613183/how-do-i-sort-a-dictionary-by-value
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
In [11]: x.items()
Out[11]: dict_items([(1, 2), (3, 4), (4, 3), (2, 1), (0, 0)])
#----------------------------------
# Sort hashMap by key/value !!!
#----------------------------------
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
# note : have to use sorted(xxx, key=yyy), instead of xxx.sorted(....)
### NOTE this !!! : x.items()
sorted_x = sorted(x.items(), key=lambda kv: kv[1])
print (sorted_x)
# [(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda kv: kv[0])
print (sorted_x)
# [(0, 0), (1, 2), (2, 1), (3, 4), (4, 3)]
# 451 Sort Characters By Frequency
import collections
class Solution(object):
def frequencySort(self, s):
count = collections.Counter(s)
count_dict = dict(count)
"""
NOTE this !!!
1. use sorted()
2. count_dict.items()
"""
count_tuple_sorted = sorted(count_dict.items(), key=lambda kv : -kv[1])
res = ''
for item in count_tuple_sorted:
res += item[0] * item[1]
return res
# dict values -> array
6]:
In [= {'a':['a1','a2','a3'], 'b':['b1','b2','b3']}
...: mydict
...:= [mydict[x] for x in mydict]
...: res
...:print (res)
...: 'a1', 'a2', 'a3'], ['b1', 'b2', 'b3']]
[[
# LC 049 Group Anagrams
# V0
# IDEA : HASH TABLE
class Solution:
def groupAnagrams(self, strs):
= {}
res for item in strs:
= ''.join(sorted(item)) # sort the string
k if k not in res: # check if exists in res
= []
res[k] # if same, put all the same string into dict k
res[k].append(item) return [res[x] for x in res] # output the result
max index
for each element in a string= 'ababcbacadefegdehijhklij'
s for k,v in enumerate(s)}
{k:v
# LC 763
# V0
# IDEA : GREEDY
class Solution(object):
def partitionLabels(self, s):
= {val:idx for idx, val in enumerate(list(s))}
d #print (d)
= []
res = set()
tmp for idx, val in enumerate(s):
#print ("idx = " + str(idx) + " tmp = " + str(tmp) + "idx == d[val] = " + str(idx == d[val]))
"""
### have to fit 2 CONDITIONS so we can split the string
# -> 1) the element has "last time exist index" with current index
# -> 2) ALL of the elements in cache with "last time exist index" should <= current index
"""
if idx == d[val] and all(idx >= d[t] for t in tmp):
+1)
res.append(idxelse:
tmp.add(val)= [res[0]] + [ res[i] - res[i-1] for i in range(1, len(res)) ]
_res return _res
# V0'
# IDEA : GREEDY
class Solution(object):
def partitionLabels(self, S):
# note : this trick for get max index for each element in S
= { c: i for i, c in enumerate(S) }
lindex = anchor = 0
j = []
ans for i, c in enumerate(S):
### NOTE : trick here
# -> via below line of code, we can get the max idx of current substring which "has element only exist in itself"
# -> e.g. the index we need to do partition
= max(j, lindex[c])
j print ("i = " + str(i) + "," + " c = " + str(c) + "," + " j = " + str(j) + "," + " ans = " + str(ans))
if i == j:
- anchor + 1)
ans.append(j = j + 1
anchor return ans
# LC 1010 Pairs of Songs With Total Durations Divisible by 60
= {}
d = 0
res = some_duration
DURATION for num in nums:
= num % DURATION # let's say sum is multiply by 60
tmp ### NOTICE THIS : (60 - tmp) % 60
if (DURATION - tmp) % DURATION in d:
+= d[(DURATION - tmp) % DURATION]
res if tmp not in d:
= 1
d[tmp] else:
+= 1 d[tmp]
sub array sum
# (algorithm book (labu) p.350)
= [1,2,3,4,5]
my_array = [0] * (len(my_array)+1)
my_array_pre = 0
cur for i in range(len(my_array)):
+= my_array[i]
cur +1] += cur
my_array_pre[i
# In [17]: print ("my_array = " + str(my_array))
# ...: print ("my_array_pre = " + str(my_array_pre))
# my_array = [1, 2, 3, 4, 5]
# my_array_pre = [0, 1, 3, 6, 10, 15]
#-----------------------------------------------
# Get sub array sum !!!!!!!
# -> nums[i..j] sum = preSum[j+1] - preSum[i]
#-----------------------------------------------
# example 1 : sum of [1,2]
1+1] - my_array_pre[0] # 1's index is 0, and 2's index is 1. (my_array = [1, 2, 3, 4, 5])
my_array_pre[
# example 2 : sum of [2,3,4]
3+1] - my_array_pre[1] # 2's index is 1, and 4's index is 3. (my_array = [1, 2, 3, 4, 5]) my_array_pre[
# LC 003
# 2 pointers + dict
# ....
= 0
l = {}
d = 0
res for r in range(len(s)):
if s[r] in d:
= max(l, d[s[r]]+1)
l = r
d[s[r]] = max(res, r-l+1)
res # ...
at least 2 indexes
with SAME sum
any 2 x-axis with same y-axis
in below charts[0, 0, 0, 0, 1, 1]
, the count starting from 0, will equal
-1, -2, -3, -4, -3, -2 -> we can find : the longest subarray with
equal number of 0 and 1 started and ended when count equals -2.
Moreover, 1st chart below shows the changes VS index
of the
sequence, We can easily find out
longest subarray length is 4
(index 2 - 6), since
index 2 and index 6 have the same y-axis
->
sum in index 2, and index 6 are the same
# 525 Contiguous Array
# V0
# IDEA : HashMap
# -> SET UP A DICT,
# -> FIND MAX SUB ARRAY LENGH WHEN COUNT(0) == COUNT(1)
# -> (WHEN cur in _dict, THERE IS THE COUNT(0) == COUNT(1) CASE)
# explaination : https://leetcode.com/problems/contiguous-array/discuss/99655/python-on-solution-with-visual-explanation
class Solution(object):
def findMaxLength(self, nums):
# edge case
if len(nums) <= 1:
return 0
# note this edge case
if len(nums) == 2:
if nums.count(0) == nums.count(1):
return 2
else:
return 0
# NOTE !!! : init hash map like below (idx=0, no solution, for [0,1,1] case)
= {0:-1} # {tmp_sum : index}
d = 0
tmp = 0
res for k, v in enumerate(nums):
if v == 1:
+= 1
tmp else:
-= 1
tmp """
Case 1 : if tmp sum in dict
# NOTE THIS : if tmp in d, return the max of (res,cur-index - index) from d with same cur-value
"""
if tmp in d:
= max(res, k - d[tmp])
res """
Case 2 : if tmp sum NOT in dict
# NOTE THIS : if tmp not in d, then use its cur value as key, index as value
"""
else:
= k ### NOTE : we just need to add index to dict at once, since what we need is MAX len of continous subarray with condition, so we only add 1st index to dist will make this work (max len subarray)
d[tmp] return res
# V0'
# https://github.com/yennanliu/CS_basics/blob/master/leetcode_python/Tree/contiguous-array.py
# explanation : https://leetcode.com/problems/contiguous-array/discuss/99655/python-on-solution-with-visual-explanation
# HASH MAP FIND EQUAL 0, 1
class Solution(object):
def findMaxLength(self, nums):
= 0
r = 0
cur ### NOTE : WE HAVE TO INIT DICT LIKE BELOW
# https://blog.csdn.net/fuxuemingzhu/article/details/82667054
= {0:-1}
_dict for k, v in enumerate(nums):
if v == 1:
+= 1
cur else:
-= 1
cur if cur in _dict:
= max(r, k - _dict[cur])
r else:
= k
_dict[cur] return r
# 523 Continuous Subarray Sum
# V0
# IDEA : HASH TABLE
# -> if sum(nums[i:j]) % k == 0 for some i < j,
# -> then sum(nums[:j]) % k == sum(nums[:i]) % k !!!!
# -> So we just need to use a dict to keep track of sum(nums[:i]) % k
# -> and the corresponding index i. Once some later sum(nums[:i']) % k == sum(nums[:i]) % k and i' - i > 1, so we return True.
class Solution(object):
def checkSubarraySum(self, nums, k):
"""
# _dict = {0:-1} : for edge case (need to find a continuous subarray of size AT LEAST two )
# https://leetcode.com/problems/continuous-subarray-sum/discuss/236976/Python-solution
# 0: -1 is for edge case that current sum mod k == 0
# demo :
In [93]: nums = [0]
...: k = 1
...:
...:
...: s = Solution()
...: r = s.checkSubarraySum(nums, k)
...: print (r)
0
i - _dict[tmp] = 1
False
"""
### NOTE : we need to init _dict as {0:-1}
= {0:-1}
_dict = 0
tmp for i in range(len(nums)):
+= nums[i]
tmp if k != 0:
### NOTE : we get remainder of tmp by k
= tmp % k
tmp # if tmp in _dict, means there is the other sub part make sub array sum % k == 0
if tmp in _dict:
### only if continuous sub array with length >= 2
if i - _dict[tmp] > 1:
return True
else:
= i
_dict[tmp] return False
# 049 Group Anagrams
# V0
# IDEA : HASH TABLE
class Solution:
def groupAnagrams(self, strs):
= {}
res for item in strs:
= ''.join(sorted(item)) # sort the string
k if k not in res: # check if exists in res
= []
res[k] # if same, put all the same string into dict k
res[k].append(item) return [res[x] for x in res] # output the result
# LC 003
# V0'
# IDEA : TWO POINTER + SLIDING WINDOW + DICT (NOTE this method !!!!)
# -> use a hash table (d) record visited "element" (e.g. : a,b,c,...)
# (but NOT sub-string)
class Solution(object):
def lengthOfLongestSubstring(self, s):
= {}
d # left pointer
= 0
l = 0
res # NOTE !!! right pointer
for r in range(len(s)):
"""
### NOTE : deal with "s[r] in d" case ONLY !!!
### NOTE : if already visited, means "repeating"
# -> then we need to update left pointer (l)
"""
if s[r] in d:
"""
NOTE !!! this
-> via max(l, d[s[r]] + 1) trick,
we can get the "latest" idx of duplicated s[r], and start from that one
"""
= max(l, d[s[r]] + 1)
l # if not visited yet, record the alphabet
# and re-calculate the max length
= r
d[s[r]] = max(res, r -l + 1)
res return res
# LC 204 Count Primes
# V0
# IDEA : dict
# https://leetcode.com/problems/count-primes/discuss/1343795/python%3A-sieve-of-eretosthenes
# prime(x) : check if x is a prime
# prime(0) = 0
# prime(1) = 0
# prime(2) = 0
# prime(3) = 1
# prime(4) = 2
# prime(5) = 3
# python 3
class Solution:
def countPrimes(self, n):
# using sieve of eretosthenes algorithm
if n < 2: return 0
= set()
nonprimes for i in range(2, round(n**(1/2))+1):
if i not in nonprimes:
for j in range(i*i, n, i):
nonprimes.add(j)return n - len(nonprimes) - 2 # remove prime(1), prime(2)
# python
# LC 036 Valid Sudoku
# V0
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
= len(board)
n return self.isValidRow(board) and self.isValidCol(board) and self.isValidNineCell(board)
def isValidRow(self, board):
= len(board)
n for r in range(n):
= [x for x in board[r] if x != '.']
row if len(set(row)) != len(row): # if not repetition
return False
return True
def isValidCol(self, board):
= len(board)
n for c in range(n):
= [board[r][c] for r in range(n) if board[r][c] != '.']
col if len(set(col)) != len(col): # if not repetition
return False
return True
def isValidNineCell(self, board):
= len(board)
n for r in range(0, n, 3):
for c in range(0, n, 3):
= []
cell for i in range(3):
for j in range(3):
= board[r + i][c + j]
num if num != '.':
cell.append(num)if len(set(cell)) != len(cell): # if not repetition
return False
return True
// java
// LC 036 Valid Sudoku
// backtrack
// (algorithm book (labu) p.311)
boolean backtrack(char[][] boolean,int i, int j){
int m = 9, n = 9;
if (j == n){
// if visit last col, start from next row
return backtrack(board, i + 1, 0);
}
if (i == m){
// found one solution, trigger base case
return true;
}
if (board[i][j] != '.'){
// if there id default number, then no need to looping
return backtrack(board, i, j + 1);
}
for (char ch = '1'; ch <= '9'; ch++){
// if there is no valid number, negelect it
if (!isValid(board, i, j, ch)){
continue;
}
[i][j] = ch;
board
// if found one solution, return it and terminate the program
if (backtrack(board, i, j+1)){
return true;
}
[i][j] = '.';
board}
// if looping 1 ~ 9, still can't find a solution
// -> change a number to loop
return false;
}
isValid(char[][] board, int r, int c, char n){
bollean for (int i = 0; i < 9; i++){
// check if row has duplicate
if (board[r][i] == n) return false;
// check if col has duplicate
if (board[i][c] == n) return false;
// check if "3 x 3 matrix" has duplicate
if (board[ (r/3) * 3 + i / 3 ][ (c/3) * 3 + i % 3] == n) return false;
}
return true;
}
# LC 1010. Pairs of Songs With Total Durations Divisible by 60
# V0
# IDEA : dict
# IDEA : NOTE : we only count "NUMBER OF PAIRS", instead get all pairs indexes
class Solution(object):
def numPairsDivisibleBy60(self, time):
= {}
rem = 0
pairs for t in time:
#print ("rem = " + str(rem))
%= 60
t if (60 - t) % 60 in rem:
"""
NOTE : this trick
-> we append "all 60 duration combinations count" via the existing times of element "(60 - t) % 60"
"""
+= rem[(60 - t) % 60]
pairs if t not in rem:
= 1
rem[t] else:
### NOTE : here : we plus 1 when an element already exist
+= 1
rem[t] return pairs
# LC 560 : Subarray Sum Equals K
# V0
# IDEA : HASH TABLE + sub array sum
# IDEA : https://blog.csdn.net/fuxuemingzhu/article/details/82767119
class Solution(object):
def subarraySum(self, nums, k):
= len(nums)
n = collections.defaultdict(int)
d 0] = 1
d[sum = 0
= 0
res for i in range(n):
sum += nums[i]
# if sum - k in d
# -> if sum - (every _ in d) == k
if sum - k in d:
+= d[sum - k]
res sum] += 1
d[return res
# V0'
# IDEA : HASH TABLE + sub array sum
class Solution:
def subarraySum(self, nums, k):
# write your code here
for i in range(1, len(nums)):
+= nums[i - 1]
nums[i] print ("nums = " + str(nums))
= {0:1}
d = 0
ans for i in range(len(nums)):
# check sub array equals k
if(d.get(nums[i] - k) != None):
+= d[nums[i] - k]
ans # update dict
if nums[i] not in d:
= 1
d[nums[i]] else:
+= 1
d[nums[i]] return ans
// LC 560 : Subarray Sum Equals K
// java
// (algorithm book (labu) p.350)
// V1 : brute force + cum sum
int subarraySum(int[] nums, int k){
int n = nums.length;
// init pre sum
int[] sum = new int[n+1];
[0] = 0;
sumfor (int i = 0; i < n; i++){
[i+1] = sum[i] + nums[i];
sum}
int ans = 0;
// loop over all sub array
for (int i=1; i <= n; i++){
for (int j=0; j < i; j++){
// sum of nums[j...i-1]
if (sum[i] - sum[j] == k){
+= 1;
ans }
}
}
return ans;
}
// (algorithm book (labu) p.350)
// V2 : hash map + cum sum
int subarraySum(int[] nums, int k){
int n = nums.length;
// map : key : prefix, value : prefix exists count
// init hash map
HashMap<Integer, Integer> preSum = new HashMap<Integer, Integer>();
// base case
.put(0,1);
preSum
int ans = 0;
= 0;
sum0_i
for (int i = 0; i < n; i++){
+= nums[i];
sum0_i // for presum : nums[0..j]
int sum0_j = sum0_i - k;
// if there is already presum, update the ans directly
if (preSum.containsKey(sum0_j)){
+= preSum.get(sum0_j);
ans }
// add prefix and nums[0..i] and record exists count
.put(sum0_i, preSum.getOrDefault(sum0_i,0) + 1);
preSum}
return ans;
}
# LC 532 K-diff Pairs in an Array
# V0
# IDEA : HASH TABLE
import collections
class Solution(object):
def findPairs(self, nums, k):
= 0
answer = collections.Counter(nums)
cnt # NOTE THIS : !!! we use set(nums) for reduced time complexity, and deal with k == 0 case separately
for num in set(nums):
"""
# [b - a] = k
# -> b - a = +k or -k
# -> b = k + a or b = -k + a
# -> however, 0 <= k <= 10^7, so ONLY b = k + a is possible
2 cases
-> case 1) k > 0 and num + k in cnt
-> case 2) k == 0 and cnt[num] > 1
"""
# case 1) k > 0 and num + k in cnt
if k > 0 and num + k in cnt: # | a - b | = k -> a - b = +k or -k, but here don't have to deal with "a - b = -k" case, since this sutuation will be covered when go through whole nums
+= 1
answer # case 2) k == 0 and cnt[num] > 1
if k == 0 and cnt[num] > 1: # for cases k = 0 -> pair like (1,1) will work. (i.e. 1 + (-1))
+= 1
answer return answer
# V0'
# IDEA : SORT + BRUTE FORCE + BREAK
class Solution(object):
def findPairs(self, nums, k):
# edge case
if not nums and k:
return 0
nums.sort()= 0
res = []
tmp for i in range(len(nums)):
for j in range(i+1, len(nums)):
if abs(nums[j] - nums[i]) == k:
= [nums[i], nums[j]]
cur
cur.sort()if cur not in tmp:
+= 1
res
tmp.append(cur)elif abs(nums[j] - nums[i]) > k:
break
return res
# LC 734. Sentence Similarity
# V0'
# https://zxi.mytechroad.com/blog/hashtable/leetcode-734-sentence-similarity/
import collections
class Solution(object):
def areSentencesSimilar(self, words1, words2, pairs):
if len(words1) != len(words2): return False
= collections.defaultdict(set)
similars for w1, w2 in pairs:
similars[w1].add(w2)
similars[w2].add(w1)for w1, w2 in zip(words1, words2):
if w1 != w2 and w2 not in similars[w1]:
return False
return True
# V0
# IDEA : array op
# -> Apart from edge cases
# -> there are cases we need to consider
# -> 1) if sentence1[i] == sentence2[i]
# -> 2) if sentence1[i] != sentence2[i] and
# -> [sentence1[i], sentence2[i]] in similarPairs
# -> [sentence2[i], sentence1[i]] in similarPairs
class Solution(object):
def areSentencesSimilar(self, sentence1, sentence2, similarPairs):
# edge case
if sentence1 == sentence2:
return True
if len(sentence1) != len(sentence2):
return False
for i in range(len(sentence1)):
= [sentence1[i], sentence2[i]]
tmp """
NOTE : below condition
1) sentence1[i] != sentence2[i]
AND
2) (tmp not in similarPairs and tmp[::-1] not in similarPairs)
-> return false
"""
if sentence1[i] != sentence2[i] and (tmp not in similarPairs and tmp[::-1] not in similarPairs):
return False
return True
# LC 146 LRU Cache
# note : there is also array/queue approach
# V1
# IDEA : Ordered dictionary
# https://leetcode.com/problems/lru-cache/solution/
# IDEA :
# -> There is a structure called ordered dictionary, it combines behind both hashmap and linked list.
# -> In Python this structure is called OrderedDict
# -> and in Java LinkedHashMap.
from collections import OrderedDict
class LRUCache(OrderedDict):
def __init__(self, capacity):
"""
:type capacity: int
"""
self.capacity = capacity
def get(self, key):
"""
:type key: int
:rtype: int
"""
if key not in self:
return - 1
self.move_to_end(key)
return self[key]
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: void
"""
if key in self:
self.move_to_end(key)
self[key] = value
if len(self) > self.capacity:
self.popitem(last = False)
# LC 438. Find All Anagrams in a String
# V0
# IDEA : SLIDING WINDOW + collections.Counter()
class Solution(object):
def findAnagrams(self, s, p):
= len(s), len(p)
ls, lp = collections.Counter(p)
cp = collections.Counter()
cs = []
ans for i in range(ls):
+= 1
cs[s[i]] if i >= lp:
- lp]] -= 1
cs[s[i ### BE AWARE OF IT
if cs[s[i - lp]] == 0:
del cs[s[i - lp]]
if cs == cp:
- lp + 1)
ans.append(i return ans
# LC 554. Brick Wall
# V0
# IDEA : HASH TABLE + COUNTER UPDATE (looping every element in the list and cumsum and
import collections
class Solution(object):
def leastBricks(self, wall):
= collections.Counter()
_counter = 0
count # go through every sub-wall in wall
for w in wall:
= 0
cum_sum # go through every element in sub-wall
for i in range(len(w) - 1):
+= w[i]
cum_sum ### NOTE we can update collections.Counter() via below
_counter.update([cum_sum])= max(count, _counter[cum_sum])
count return len(wall) - count
// java
// LC 325
public int maxSubArrayLen_0_1(int[] nums, int k) {
// Map to store (prefixSum, index)
Map<Integer, Integer> preSumMap = new HashMap<>();
.put(0, -1); // Initialize for subarrays starting from index 0
preSumMap
int curSum = 0;
int maxSize = 0;
for (int i = 0; i < nums.length; i++) {
+= nums[i];
curSum
/**
*
* TODO: check if `preSum == k` already existed before (within loop over nunms)
*
* -> if preSum == k existed
* -> (let's say current idx = j, and a previous idx = i, can make sum(i, j) == k)
* -> `preSum(j) - preSum(i) = k` !!!!
* -> preSum(j) if what we have (preSum)
* ----> so need to check if `preSum(j) - k` exists in map !!!
*/
// Check if there's a prefix sum such that curSum - prefixSum = k
/**
* Prefix sum
*
*
* The prefix sum approach works because any subarray sum can be expressed in terms of two prefix sums:
*
*
* sum of subarray[i,j] = prefixSum[j] - prefixSum[i-1]
*
*
* Where:
* • prefixSum[j] is the cumulative sum of the array up to index j.
* • prefixSum[i-1] is the cumulative sum of the array up to index i-1.
*
* Rewriting this:
*
* -> prefixSum[j] - prefixSum[i-1] = k
*
* -> prefixSum[i-1] = prefixSum[j] - k
*
*
* Thus, the task is to find a previous prefix
* sum (prefixSum[i-1]) such that the
* difference between the current
* prefix sum (prefixSum[j]) and that value equals k.
*
*
*
* How the Code Works
*
* 1. Tracking Prefix Sums:
* • curSum is the cumulative prefix sum up to the current index i.
* • The map preSumMap stores previously seen prefix sums as keys, with their earliest index as the value.
* 2. Checking for Subarrays:
* • At any index i, the condition curSum - k checks if there exists a previously seen prefix sum that, when subtracted from the current cumulative sum, gives the desired subarray sum k.
*
* 3. Why It Covers All Possible Subarrays******:
* • The map contains all prefix sums seen so far, so it inherently includes all potential starting points of subarrays.
* • If a subarray [start, i] has a sum equal to k, the difference curSum - k corresponds to the prefix sum at start - 1. Since the map stores all previously seen prefix sums, this difference is guaranteed to be checked.
*
*/
if (preSumMap.containsKey(curSum - k)) {
= Math.max(maxSize, i - preSumMap.get(curSum - k));
maxSize }
// Add current prefix sum to the map if not already present
.putIfAbsent(curSum, i);
preSumMap}
return maxSize;
}
// java
// LC 1257
// V0-1
// IDEA: HASHMAP (fixed by gpt)
// TODO: validate
public String findSmallestRegion_0_1(List<List<String>> regions, String region1, String region2) {
// Map each region to its parent
/**
* NOTE !!!
*
* map : {child : parent}
*
* -> so the key is child, and the value is its parent
*
*/
Map<String, String> parentMap = new HashMap<>();
for (List<String> regionList : regions) {
String parent = regionList.get(0);
for (int i = 1; i < regionList.size(); i++) {
.put(regionList.get(i), parent);
parentMap}
}
// Track ancestors of region1
/** NOTE !!!
*
* we use `set` to track `parents` (ancestors)
* if exists, add it to set,
* and set `current region` as its `parent`
*
*/
Set<String> ancestors = new HashSet<>();
while (region1 != null) {
.add(region1);
ancestors= parentMap.get(region1);
region1 }
// Traverse region2’s ancestors until we find one in region1’s ancestor set
while (!ancestors.contains(region2)) {
= parentMap.get(region2);
region2 }
return region2;
}