lc Flashcards

(65 cards)

1
Q

121: Max profix in an array
Input: prices = [7,1,5,3,6,4]
Output: 5

think of 2 ways

A

SOLUTION 1:
left and right pointers
if A[i] > A[j]:
i = j, j += 1
else:
record max
j += 1

SOLUTION 2:
if num < min: reset min and max
if num > max: update max, record res

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

Input: nums = [1,2,3,1]
Output: true
Example 2:

Input: nums = [1,2,3,4]
Output: false
Example 3:

Input: nums = [1,1,1,3,3,4,3,2,4,2]
Output: true

A

set,
sort

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
  1. Product of Array Except Self

Example 1:

Input: nums = [1,2,3,4]
Output: [24,12,8,6]
Example 2:

Input: nums = [-1,1,0,-3,3]
Output: [0,0,9,0,0]

A

count the 0’s
multiply everything
if zeros_count >= 2: return all 0’s
if no zeros:
if 1 zero at index i:
res = product
else:
res[i] = product / nums[i]

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

Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6

A

Key Idea:
ensure that the running sum is (+)

Solution: write this without i and k
for i in nums length:
if nums[k..i] < 0:
res = max nums[k..i], res
k = i // running_sum starts at k
else:
running_sum = nums[k..i] // running_sum += nums[i]
res = max(running_sum, res)

CODE:
running_sum = 0
res = nums[0]
for num in nums:
running_sum += num
if running_sum < 0:
res = max(res, running_sum)
running_sum = 0
else:
res = max(res, running_sum)
return res

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
  1. Find Minimum in Rotated Sorted Array

Input: nums = [3,4,5,1,2]
Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.

A

Note:
if nums[l] >= nums[r], we have to check for condition nums[mid] > nums[r]
MIN = nums[0]
while l <= r:
mid = (l + r) // 2
if nums[l] >= nums[r]:
if nums[mid] > nums[r]:
l = mid + 1
else:
r = mid - 1
else:
r = mid
MIN = min(MIN, nums[mid])

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
  1. Search in Rotated Sorted Array
A

Note:
if we use while l <=r, we must update l and r points as += 1, -= 1 respectively,
we can also return mid from this

while l <= r:
if nums[mid] == target: return mid

# do normal binary search if Nl < Nr
if nums[l] < nums[r]:
    if nums[mid] < target: l = mid + 1
    else: r = mid - 1

# at this point, nums[mid] could be either >= nums[l]
# or < nums[l]
# for each case, check which side target should be in
else: 
    if nums[mid] >= nums[l]:
        if target >= nums[l] and target <= nums[mid]:
            r = mid - 1
        else:
            l = mid + 1
    
    else:
        if target >= nums[mid] and target <= nums[r]:
            l = mid + 1
        else:
            r = mid - 1

if nums[mid] == target: return mid
return -1

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

sort nums
for i in nums length:
if nums[i] == previous number: continue

use left and right pointer method and to find pairs that equal to current number. 

while l < r:
    sum = nums[i] + nums[l] + nums[r]
    if sum < 0:
        l += 1
    elif sum > 0:
        r -= 1
    else:
        we've found a target, however, we want to move left and right pointers inward to avoid duplicates
        res.append([nums[i], nums[l], nums[r]])

        while l < r and nums[l] == nums[l - 1]: l += 1
        while l < r and nums[r] == nums[r + 1]: r -= 1
return res
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q
  1. Container With Most Water
A

UNDESTAND why it works:

while l < r:
res = max(res, area(height,l,r))
if height[l] > height[r]:
r -= 1
else:
l += 1
return res

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q
  1. Climbing Stairs
A

”””
dp[i] = dp[i-1] + dp[i-2]
“””
if n <= 3:
return n

one, two = 1, 2
three = 3
for i in range(3,n+1):
tmp = one + two # three
one = two
two = tmp
three = tmp
return three

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q
  1. Coin Change.
    review: bottom up and top down approach (skipped top down approach)
A

BOTTOM
for i in range(amount + 1):
for coin in coins:
if i- coin == 0:
dp[i] = 1
elif i - coin > 0:
dp[i] = min(dp[i-coin] + 1, dp[i])

can be simplified to:
for i in range(amount + 1):
for coin in coins:
if i - coin >= 0:
dp[i] = min(dp[i-coin] + 1, dp[i])

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q
  1. Longest Increasing Subsequence
    REVIEW:
A

dp[i] = max(dp[i],1 + dp[k]) if nums[i] > nums[k]
dp[i] = 1 if nums[i] <= nums[k]
where:
k = is the range form 0..i-1

for i in range(len(nums)):
max_i = 0
for j in range(i):
if nums[i] > nums[j]:
dp[i] = max(dp[i], 1 + dp[j])

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q
  1. Longest Common Subsequence
A

TOP DOWN:
try t1[0] and t2[0]
if match:
res += 1
advance
else try:
t1[0] and t2[1] +
t1[1] and t2[0]

    base case:
    if indices are out of range

then add cache to it

BOTTOM UP:
dp = initialize 2d array of size (M+1)*(N+1)

iterate from bottom right to top left
if characters match:
dp[i][j] = 1 + dp[i+1][j+1]
else:
dp[i][j] = max(dp[i+1][j] , dp[i][j+1])
return dp[0][0]

CODE:
for i in range(len(s1)-1, -1,-1):
for j in range(len(s2)-1, -1, -1):
if s1[i] == s2[j]:
dp[i][j] = 1+ dp[i+1][j+1]
else:
dp[i][j] = max(dp[i+1][j] , dp[i][j+1])

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q
  1. Word Break
    REVIEW neetcode solution
A

TOP DOWN RECURSIVE:
add memoization to the following code:
def bfs(cur_s):

        if cur_s in wordDict: return True
        if cur_s in seen: seen[cur_s]

        for i in range(len(cur_s),-1,-1):
            if cur_s[i:] in wordDict:
                if bfs(cur_s[:i]):
                    return True

        return False

BOTTOM UP:
- j represents the end of the prefix of the string.
- dp[i] represents whether the substring up to index s[0..i-1]
- if dp[j] is true, and dp[j..i-1] is also true, then the entire substring dp[i] is True
- since j represents every possible prefix, the prefix of “” must also exists, thus we set dp[0] to True,

    wordSet = set(wordDict)
    dp = [False] * (len(s) + 1)
    dp[0] = True

    for i in range(1,len(s) + 1):
        for j in range(i):
            if dp[j] and s[j:i] in wordSet:
                dp[i] = True
                break
    
    return dp[-1]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q
  1. Combination Sum IV
A

answer at i = sum of (
if rem == 0, then theres only 1 way = 1
if rem != 0, then the number of count is dp[rem]
)

BOTTOM UP APPROACH:

dp = [0] * (target+1)
dp[0] = 1
for i in range(target+1):
for num in nums:
if num > i: break
dp[i] += dp[i-num]
return dp[target]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q
  1. House Robber
A

dp[i] = max(dp[i-2] + nums[i], dp[i-1])

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q
  1. House Robber II
A

return max(
nums[0],
house_robber1(nums[1:]),
house_robber1(nums[:-1])
)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q
  1. Decode Ways
    Conceptualize, Know how to write in bottom up way
A

TOP DOWN:
def dfs(cur_nums):
if str(cur_nums) in dp: return dp[str(cur_nums)]
if not cur_nums: return 1
if cur_nums[0] == ‘0’: return 0

res = dfs(cur_nums[1:])

if len(cur_nums) >= 2 and int(cur_nums[:2]) <= 26:
    res += dfs(cur_nums[2:])
        
dp[str(cur_nums)] = res
return res

BOTTOM UP:
if s[0] == “0”:
return 0

two_back = 1
one_back = 1
for i in range(1, len(s)):
current = 0
if s[i] != “0”:
current = one_back
two_digit = int(s[i - 1: i + 1])
if two_digit >= 10 and two_digit <= 26:
current += two_back
two_back = one_back
one_back = current

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q
  1. Unique Paths
A

dp[i][j] = dp[i+1][j] + dp[i][j+1]

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

STRINGS:

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q
  1. Jump Game
A

iterate backwards
if cur_jump + cur_index >= last_successful_index
then last_successful_index = current_index
True if last_successful_index == 0

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q
  1. Longest Substring Without Repeating Characters
A
  • use a set and add/remove from left and right pointers
  • before loop starts, make sure that set is unique by updating left pointer
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q
  1. Longest Repeating Character Replacement
A
  • length - highest unique char <= # of allowed replacements
  • at every iteration, compare the highest with the count of the current character in the substring
  • update l while it is not valid
  • record result
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q
  1. Minimum Window Substring

review optimal

A

BRUTE FORCE:
create a dictionary of both s1 and s2
iterate s1:
while map1 satisfies map2:
record min res
remove char at indexL from map
increment indexL

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q
  1. Valid Anagram
A

solution 1:
- compare sorted values

solution 2:
- create a map from the first string
- iterate the second string and decrement the map
- return length of map == 0

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
49. Group Anagrams
Idea: group the words by their sorted order implementation create a dictionary for every word: sort it use the sorted version as the key append the current word to the dictionary using the sorted key
26
20. Valid Parentheses
if matches open breaces, append if closed braces, compare if stack empty early, return False return arry has 0 length
27
125. Valid Palindrome
two pointer
28
5. Longest Palindromic Substring
expand from middle in two ways: - single piont - double point
29
271. Encode and Decode Strings
make sure that the prefix tells you about the words afterwards encoding: res + length(string) + "#" + string decoding: find the # position turn values up to # into an integer append to list
30
104. Maximum Depth of Binary Tree
level order traversal
31
100. Same Tree
level order traversal
32
226. Invert Binary Tree
if not node, return node invert left invert right switch l and right pointers return root
33
124. Binary Tree Maximum Path Sum
joined val joined_val = node.val + l + r split_val = max(node.val, node.val + l, node.val + r) self.res = max(self.res, split_val, joined_val) # ret value return split_val
34
297. Serialize and Deserialize Binary Tree understand tree properties for: dfs, bfs, inorder, level order with respect to stacks
Serialize: call in order on it Deserialize: call in order while popping the very first node LEVEL ORDER: Serialize: Level Order Traversal => ''.join(array) Desearialize: if string is '': return None root is the first val add to queue we want to go through all the nodes by doing.. while queue exist: get node from queue update left node child if not none update arr index get node from queue update right node child if not none update arr index return root while queue: node = queue.popleft() if nodes[index] != "None": node.left = TreeNode(int(nodes[index])) queue.append(node.left) index += 1 if nodes[index] != "None": node.right = TreeNode(int(nodes[index])) queue.append(node.right) index += 1
35
105. Construct Binary Tree from Preorder and Inorder Traversal
**note: the index of the root node in inorder array also represents the number of nodes that the left subtree has** root = preorder[0] Left: preorder[1: inorder.indexOf(root) + 1] inorder[0: inorder.indexOf(root)] Right: preorder[inorder.indexOf(root) + 1: ] inorder[inorder.indexOf(root) + 1: ] OPTIMIZE: - use a hashmap - convert to: def helper(pre_left, pre_right, in_left, in_right):
36
572. Subtree of Another Tree
compare the two tress in a in pre order format
37
230. Kth Smallest Element in a BST redo
stack = [] while True: while root: stack.append(root) root = root.left root = stack.pop() k -= 1 if not k: return root.val root = root.right
38
98. Validate Binary Search Tree
stack = [] node = root prev = -float('inf') while stack or node: while node: stack.append(node) node = node.left # current node node = stack.pop() if node.val <= prev: return False prev = node.val # right node node = node.right if node and node.val <= prev: return False return True
39
235. Lowest Common Ancestor of a Binary Search Tree
Recursive Logic: - if one is greater and one is smaller than current node, return current node - if current node is p or q, return current node - if both nodes are greater than current node, return searched right node - if both nodes are smaller than current node, return searched left node Iterative Logic: same thing as above but use an infinite loop and update root node
40
208. Implement Trie (Prefix Tree) should learn how to write it iteratively
Recursive: def insert(self, word: str) -> None: def dfs(node, word): if not word: node['stop'] = True return # add current character to current node if word[0] not in node: node[word[0]] = {} dfs(node[word[0]], word[1:]) dfs(self.root, word)
41
211. Design Add and Search Words Data Structure should learn how to write it iteratively
Solution idea: search all possible children keys when wild card is reached def helper(root, word): # base case if not word: return True if root.stop else False # search all possible values when wild card is reached elif word[0] == '.': for v in root.chars.values(): if helper(v, word[1:]): return True return False # dfs elif word[0] not in root.chars: return False else: return helper(root.chars[word[0]], word[1:])
42
212. Word Search II
sometimes we can generate/memoize from the target instead of the given data. Technique: leaving crumbs method + building Trie from target instead of data. ALGORITHM: Note: - path is used for keeping track of the words that we want to add to result - visited prevents us from visiting the same cell again build a trie from the words use the trie to run dfs on the matrix for every cell if trie.node.end_of_word == True, add to result add visted cordinates to trie add current char to path call dfs remove visited cordinates from trie remove current char from path REMINDER: path must be added THEN poped after dfs'ing must not forget __init__ when build classes Code: def dfs(i,j, node, visited, path): if (i,j) in visited: return if i >= ROW or i < 0 or j >= COL or j < 0: return char = board[i][j] # Here you have to pass the child node to DFS rather than the current node if char not in node.children: return visited.add((i,j)) path.append(char) # Here you should check if we reached the end of a word in the trie. This should be done with node.children[char].stop, not node.stop if node.children[char].stop: res.add(''.join(path)) cords = [(1,0),(-1,0), (0,1), (0,-1)] for cord in cords: x, y = cord dfs(i+x,j+y, node.children[char], visited, path) # here you are now passing the child node, not the current node visited.remove((i,j)) path.pop()
43
110. Balanced Binary Tree
dfs then check: if abs(left - right) > 1: return -1 return max(left, right) + 1
44
232. Implement Queue using Stacks
move to the other queue in the same order
45
169. Majority Element Given an array nums of size n, return the majority element. The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.
use counter to keep track in the end, the number with a positive counter is the result
46
67. Add Binary Review
summ = ca + cb + carry cur_bit = summ % 2 # Current bit is the remainder when dividing by 2 carry = summ // 2 # Carry is the quotient when dividing by 2 res = str(cur_bit) + res
47
543. Diameter of Binary Tree
instead of considering where null node yields -1 diameter, have it yield 0 and not update the root diameter with an extra value. we basically want to calculate the height of the node def dfs(node): if not node: return 0 left_length = dfs(node.left) right_length = dfs(node.right) Update the diameter at every node self.res = max(self.res, left_length + right_length) Return the length of the longest path which passes through this node return max(left_length, right_length) + 1
48
57. Insert Interval review Logn solution
add intervals to the result list based on the following conditions: - if current_interval.end < newInterval.start: add current_interval - if current_interval.start > newInterval.end: add newInterval, then join the rest - else: this this means that there must be overlap. So we update new interval = newInterval.start = min(newInterval.start, cInterval.start), newInterval.end = min(newInterval.end, cInterval.end) res.append(newInterval) return res
49
542. 01 Matrix graph redo on your own
**BFS Solution:** Create a copy of mat, we'll call it matrix. Use a data structure seen to mark nodes we have already visited and a queue for the BFS. Put all nodes with 0 into the queue. We will also track the level/number of steps with each queue entry. Mark these nodes in seen as well. Perform the BFS: - While queue is not empty, get the current row, col, steps from the queue. - Iterate over the 4 directions. For each nextRow, nextCol, check if it is in bounds and not already visited in seen. - If so, set matrix[nextRow][nextCol] = steps + 1 and push nextRow, nextCol, steps + 1 - onto the queue. Also mark nextRow, nextCol in seen. **Dynamic Programming:** Create a copy of mat, we'll call it dp. - Iterate row by row, column by column. At each row, col: - Initialize minNeighbor to a large value. This represents the minimum value of dp from the cells we could have arrived from. - Making sure to stay in bounds, check the two cells we could have arrived from: row - 1, col and row, col - 1. - Update minNeighbor with their dp values. - Set dp[row][col] = minNeighbor + 1. Iterate over dp again but in reverse order. At each row, col: - Initialize minNeighbor to a large value. - Making sure to stay in bounds, check the two cells we could have arrived from: row + 1, col and row, col + 1. - Update minNeighbor with their dp values. - If minNeighbor + 1 is less than dp[row][col] (the minimum distance if we only considered down-right paths), then update it.
50
973. K Closest Points to Origin
review quickpartition
51
150. Evaluate Reverse Polish Notation Input: tokens = ["2","1","+","3","*"] Output: 9 Explanation: ((2 + 1) * 3) = 9
use stack
52
155. Min Stack
stack with tuples (x,y) - x: actual value - y: min value at current level optimize by using 2 stacks: - stack: holds original stack values - min_stack (x,y)[]: - x is the value, y is the count - keepds track of the min value at the current level. If newly added value is the same as top of min_stack, increment the y count - same for popping
53
39. Combination Sum redo
- For each target value t from 1 to target, iterate through each number num in candidates. If num is greater than t, skip to the next iteration. - For each combination prev_comb that sums up to t - num, append a new combination consisting of prev_comb followed by num to dp[t], ensuring that this doesn't result in a permutation. need to initialize 0 because if t-num == 0, we want to add [] + [num] to dp[t] dp = {0: [[]]} for t in range(1, target + 1): for num in candidates: if num > t: break if t - num not in dp: continue iterate combinations for t - num for prev_comb in dp.get(t - num): # ensure unique permutation if prev_comb and prev_comb[-1] > num: continue # if t doesn't already exist, create it if t not in dp: dp[t] = [] # add prev_combination with current number to dp[t] new_combination = prev_comb + [num] dp[t].append(new_combination)
54
46. Permutations
DFS: iterate and make copies
55
236. Lowest Common Ancestor of Binary Tree
sub optimal: 1. if find target.left == True and find target.right == True return root 2. if only (either left or right) is true, return self.lowestCommonAncestor(left or right), depending on which side is true Optimal: dfs on left and right first if both true, return root if root == p or q, return root if dfs from left is not None: return dfs from left if dfs from right is not None: return dfs from right
56
981 time-based-key-value-store
# Find the position using bisect_right a map, that points to a Node. This node contains an array of timestamps and a dictionary. set: append timestamp to array update dictionary get: index of dictionary = binary search for timestamp in array helpful - learn bisect: pos = bisect.bisect_right(timestamps, timestamp) If the exact timestamp is not present, adjust the position if pos > 0: return sub_maps[timestamps[pos - 1]] else: return "" l, r = 0, len(timestamps)-1
57
721. Accounts Merge review and redo
redo when reviewing graphs: **brute:** build a mapping between {name => [emails]} while building, find union between account sets by: while i < len(dic[name]): if emails & dic[name][i]: # Intersection of two sets emails |= dic[name][i] # Union of two sets dic[name].pop(i) # Remove the merged set of emails else: i += 1 dic[name].append(emails) ** DFS:** ** union Find:**
58
75. Sort Colors you failed. redo
Dutch National Flag problem - Initialize three pointers: l at the start, i at the start, and r at the end of the array. - If nums[i] is 0, swap nums[i] with nums[l], then increment both l and i. - If nums[i] is 1, just move to the next element by incrementing i. - If nums[i] is 2, swap nums[i] with nums[r] and then decrement r, but don't
59
416. Partition Equal Subset Sum
* Idea * - it is a include exclude problem to build subarrays ** todo ** - convert top bottom to bottom up - link this problem with the maximum substirng. the one that builds the tree by deciding to inlcude or exclude - lots of problems. review notion ** Top Down ** - think of subtraction code: @lru_cache(maxsize=None) def dfs(nums: Tuple[int], n: int, subset_sum: int) -> bool: # Base cases if subset_sum == 0: return True if n == 0 or subset_sum < 0: return False # binary decision. to keep or not to keep result = ( dfs(nums, n - 1, subset_sum - nums[n - 1]) or # take dfs(nums, n - 1, subset_sum)) # not take return result ** Bottom Up 2D ** - ** mistake 1: checks for array ** only, not subsets for i in range(len(nums)): for j in range(0, i): print(sum(nums[j:i])) ** mistake 2: ** brute force will be 2^n
60
8. String to Integer (atoi)
Key Points: - `res = res * 10 + int(s[i])` times 10 then add integer - `2**31-1` or `-2**31-1`
61
54. Spiral Matrix
Key Points: - use borders - include the ending borders when traversing - make sure that the second time the iterate the row or column, they are itterating on a different row or colum. can check this by applying `if topborder < botborder` or `if leftborder < rightborder`
62
78. subsets - review binary solution
binary backtrack cascading
63
17. Letter Combinations of a Phone Number
dfs level order traversal
64
76. Minimum Window Substring
have and needs expand and contract use table and counter
65