Amazon Flashcards

(92 cards)

1
Q

Merge k sorted lists

A

Idea:
Instead of iterating over each of k lists one by one, we can try merging a set of 2 lists and then merge these merged lists and so on

Algorithm:
-define mergeList function with two lists l1 and l2 params as follws
-declare a new empty dummy node and assign it to tail
-while l1 and l2
-if l1.val<l2.val, then tail.next = l1, l1 = l1.next
-else tail.next = l2, l2 = l2.next
-end if else
-tail = tail.next
-end while
-if l1, tail.next = l1
-if l2, tail.next = l2
-return dummy.next

-if not lists or len(lists) is 0, return None
-while len(lists) > 1
-mergedLists = []
-for i from 0 to len(lists) with step of 2
-l1 = lists[i]
-l2 = lists[i + 1] only if i + 1 < len(lists) else None
-add mergeList(l1, l2) to mergedLists array
-end for
-lists = mergedLists
-end while
-return lists[0]

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

Median of two sorted arrays

A

Idea:
Aim is to find the left partition without merging two arrays. We find the partition in one array using binary search, and then the other based on length. Then we change binary search conditions based on the whether the partition has been correct or not

Algorithm:
-Assign both the arrays to A and B
-keep smaller one in B
-calculate total and half length
-initialize l and r to binary search on A
-while True
-i = (l + r) // 2
-j = half - i - 2 (i.e. the remaining partition in the B)
-Aleft = A[i] if i >= 0 else float(‘-inf’)
-Aright = A[i + 1] if (i + 1) < len(A) else float(‘inf’)
-Bleft = B[j] if j >= 0 else float(‘-inf’)
-Bright = B[j + 1] if (j + 1) < len(B) else float(‘inf’)
-if Aleft <= Bright and Bleft <= Aright, (partitions are correct)
-if total is odd, return min(Aright, Bright)
-else, return (max(Aleft, Bleft) + min(Aright, Bright)) / 2
-end if else
-elif Aleft > Bright, r = i + 1 (A partition is bigger than needed)
-else l = i + 1 (A partition is smaller than required)

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

Word search 2

A

Idea:
Using original word search for each is inefficient. Use trie to first store the words given, and then run dfs on each cell and evaluate whether the word is formerd or not

Algorithm:
-Define TrieNode class
-constructor, define children as set and isWord boolean
-define the addWord function

-Initialize root TrieNode and run addWord on each provided word
-Get rows and cols, and define answer and visited as set
-Define dfs function with params r, c, word and node as follows
-if not in bounds or (r, c) in visited or current position not in node.children, return
-add (r, c) to visited
-node = node.children[board[r][c]]
-word += board[r][c]
-if node.isWord, add word to answer
-call dfs in four directions
-remove (r, c) from visited (Backtracking)

-Double loop for through rows and columns
-call dfs on each with root and “” as other params

-return list(answer)

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

Find median from data stream

A

Idea:
Data is not ordered, so instead of using an array. We will use two heaps
Small heap will be a max heap
Large heap will be a min heap
Each element in small heap will be less than the smallest in large heap

Solution:
1. INIT
-just initialize two heaps, small and large

  1. ADD NUM
    -push -1*num to small heap
    -if small and large exists and (largest in small ) > (smallest in large), then pop from small and insert into large
    -if small heap longer than large heap + 1, pop from small and insert to large
    -if large heap longer than small heap + 1, pop from large and insert into small
  2. FIND MEDIAN
    -if small heap longer, return largest in small
    -if large heap longer, return smallest in large
    -else, return (largest in small + smallest in large) / 2
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Word ladder

A

Idea:
We need to find the words which differ from each other by only one letter, so e.g. hit and hot, follow the pattern h*t.
So we will build an adjacency list of such patterns and then use bfs to tranverse the graph and find the shortest path

Algorithm:
-if endword not in wordList, return 0
-declare nei as default dict
-append beginning word to wordList
-for every word in wordList
-for j at every position in the current word
-pattern = word[:j] + ‘*’ + word[j + 1:]
-nei[pattern].append(word)
-end for
-end for
-declare visited set and a queue and add beginword to it, declare answer as 1
-while queue
-for i in range(len(q))
-word = popleft()
-if word is endword, return answer
-for j at every position in current word
-create patttern
-for every neighbor in nei[pattern]
-if neighbor not visited, add neighbour to visited and queue
-end if
-end for
-end for
-increment answer
-end while
-return 0

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

Integer to english words

A

Idea:
We need to do some repeated work every three digits
So we first extract the last 3 digits, construct a string and then repeat

Algorithm:
-if num is 0, return “Zero”
-define ones_map as {number: string} for numbers 1 to 20
-define tens_map as {number: string} for numbers 20, 30, …., 90

-define get_string function with number for param as follows
-res = []
-hundreds = n // 100
-if hundreds, res.append(ones_map[hundreds] + “ Hundred”)
-end if
-last_2 = n % 100
-if last_2 >= 20
-tens, ones = last_2 // 10, last_2 % 10
-res.append(tens_map[tens * 10])
-if ones, then res.append(ones_map[ones])
-elif last_2, res.append(ones_map[last_2])
-end if else
-return “ “.join(res)

-define postfix as [””, “ Thousand”, “ Million”, “ Billion”]
-i = 0
-answer = []
-while num
-digits = num % 1000
-s = get_string(digits)
-if s, answer.append(s + postfix[i])
num = num // 1000
i += 1
-end while

-answer.reverse()
-return “ “.join(answer)

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

Minimum window substring

A

Idea:
We use two pointer approach along with the hashmaps. Build map of string t and keep changing window simultaneously. Move right till be have all we need. Then we move left until we are missing something. This way, we get minimum

Algorithm:
-if t empty, return “”
-define hashmaps for count_t and window
-construct count_t hashmap
-declare have and need as 0 and len(count_t)
-declare answer and answer_len as [-1, -1] and float(“inf”) respectively
-l = 0
-for r in range of length s
-c is character at r
-window[c] += 1
-if c in t hashmap and count_t[c] equals window[c], have += 1
-while have == need
-if (r - l + 1) < answer_len, reassign answer and answer_len
-window[s[l]] -= 1
-if s[l] in t hashmap and window[s[l]] < count_t[s[l]], have -= 1
-l += 1
-end while
-end for

-l, r = answer
-if answer is float(“inf”), return “” or return s[l : r + 1]

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

Binary tree maximum path sum

A

Idea:
Do a dfs to return the maximum sum without the split. Calculate the maximum sum with the split every time and change the global variable if needed

Algorithm:
-answer = root.val
-define dfs function with root for param as follows
-nonlocal answer
-if not root, return 0
-recursively calculate left_max and right_max
-reassign left_max to max of itself or 0, and same for right_max
-answer = max(answer, root.val + left_max + right_max)
-return root.val + max(left_max, right_max)

-dfs(root)
-return answer

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

Serialize and deserialize binary tree

A

Idea:
Use preorder traversal to recursively construct the array and then the string. Replace the None with N. Do the same backwards

Solution:
1. Serialize
-res = []
-define dfs with node for param as follows
-if not node, res.append(“N”), return
-res.append(str(node.val))
-dfs(node.left)
-dfs(node.right)

-dfs(root)
-return “,”.join(res)

  1. Deserialize
    -values = data.split(‘,’)
    -self.i = 0
    -define dfs function as follows
    -if values at self.i is “N”, inc self.i, return None
    -node = TreeNode(int(values[self.i]))
    -inc self.i
    -node.left = dfs()
    -node.right = dfs()
    -return node

-return dfs()

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

Alien dictionary

A

Idea:
Build an adjacency list based on the words provided. Then perform topological sort and post order DFS

Algorithm:
-construct adjacency list for all the letters as follows adj = {c: set() for w in words for c in w}
-for i in range(len(words) - 1)
-w1, w2 = words[i], words[i + 1]
-minLen = min(len(w1), len(w2))
-if len(w1) > len(w2) and w1[:minLen] == w2[:minLen], return””
-for j in range(minLen)
-if w1[j] != w2[j]
-adj[w1[j]].add(w2[j])
-break
-end if
-end for
-end for

-declare visited and answer as empty dictionary and array respectively
-define dfs function with c for param as follows
-if c in visited, return visited[c] (False if just visited, True if in current path, thus cycle)
-visited[c] = True
-for nei in adj[c]:
-if dfs(nei), return “”
-end for
-visited[c] = False
-answer.append(c)
-end func

-for c in adj:
-if dfs(c), return “”
-end for

-answer.reverse()
-return ““.join(answer)

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

Longest palindromic substring

A

Idea:
Start with individual letter, expand using l and r pointers continuously checking if the contained string is palindromic or not. Keep saving the max results

Algorithm:
1. For odd substrings
For each character, start with l and r at i
Bounds check and character equivalence check
Decrement l and increment r

  1. For even substrings
    Same but start with l and r at i and i + 1 respectively
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Roman to integer

A

Idea:
If the value of current character is less than the value of character after it, we have to subtract the current value from the result

Algorithm:
Define hashmap of (character, value)
Iterate through the string
If (i + 1) < len(s) and map(curr) < map(next)
answer -= curr
else
answer += curr

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

String to integer (atoi)

A

Idea:
We need to get to the point in the string where actual number (if it exists) starts

Algo:
First init result as 0 and sign as 1
First use strip to remove whitespace
Return 0 if no string at that point

Check the signage and assign the sign appropriately
Run the loop on remaining string
result = result * 10 + int(char)
break if the character is not digit
result = result * sign

Check bounds and return

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

Two Sum (Unsorted input)

A

NAME?

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

Integer to roman

A

NAME?

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

Valid paranthesis

A
  • Create hashmap of (closing, opening)
  • Iterate through string
  • if bracket in map
  • if stack and top of stack == map(bracket), then pop
  • else return False
  • else stack append
  • Return true of stack empty else false
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Valid sudoku

A
  • Start outer loop till 9
  • Define set for horizontal and vertical
  • Start inner loop till 9
  • Check for (i, j) in horizontal set and (j, i) in vertical set
  • Return False if exists
  • Add to set if not and the position is not ‘.’
    -End both loops

For box check
Define a dictionary
- Start outer loop till 9
- a = i // 3
- Start inner loop till 9
- b = j // 3
- If (a, b) not in dictionary, define it as set
- If (i, j) in the dictionary of (a, b), return False
- Else add (i, j) to the (a, b) dictionary

return True

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

Combination sum

A

Idea:
- Draw the recursion tree
- We first need to make decision on first element, either include it or not
- And then based on the bounds and current total, make other decision

Algo:
- Define dfs function with current array and total as param
- If the target is achieved, add the current copy to the answer
- If outside bounds or target exceeded
- return
- Decision 1: add the current candidate, and call dfs on it with new total
- Decision 2: pop the element to remove the recently added candidate and call the dfs on i + 1 element

Call the dfs on zeroth element

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

Permutations

A

Recursive idea:
We start with the empty combination, add the last element, then add the other on either side of it. Then we add next element to all possible positions within the above result (i.e. at start, middle, end)

Recursive algo:
- Define base case of if len(array) is 0 then return [[]]
- Call the self function and pass the array without the first element. Retrieve the results in the variable (perm)
- Define result as []
- For each p in perm
- For i in len(p) + 1
- Make a copy of p and insert array[0] at i position
- add the updated copy to answer
- end for
- end for
Return answer

Iterative algo:
- answer = [[]]
- for each number
- new_perm = []
- for each answer
- for each position in answer
- make a copy of answer and insert into position the current number and append to new_perm
- end for
- end for
- answer = new_perm
- end for

return answer

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

Merge intervals

A
  • Sort intervals by start time
  • Iterate through the intervals
  • Insert 1st interval in the answer
  • For rest, if current interval start is less or equal to last interval end, change last interval time to max of either
  • else append to answer
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Rotate list

A

Idea:
We need to find the pivot point at length - k, and then reassign pointers, i.e. join end to the start and return new head

Algorithm
Base case: If not head, return head
Calculate length and tail simultaneously
length = 1, tail = head. Run loop till tail.next
k = k % length
if k is 0, return head

curr = head
loop till length-k-1, curr = curr.next
Reassign pointers:
new_head = curr.next
curr.next = None
tail.next = head

return new_head

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

Minimum path sum

A

Idea:
Calculate minimum path sum for all the positions in the grid one by one, and eventually, we will have the minimum path sum for bottom right

Algorithm:
- Define dp array
- dp[i, j] = min(dp[i - 1, j], dp[i, j - 1]) + gri[i, j]
(except if the cell is on boundary, in which case it will be directly sum with either the left one or above one)
- Return dp[m - 1, n - 1]

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

Word search

A

Idea:
Run the dfs from each position in the grid recursively and compare the letter in that cell

Algorithm:
Define m and n, define path as empty set
Define dfs function with row, col and index for params as follows:
- if out of bounds or board letter != word index or position already in path set, return False
- Add position to path set
- store OR of dfs in 4 directions in result
- remove position from path
- return result

  • Brute force through the board and call dfs, if True, return True
    return False
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Validate binary search tree

A

Idea:
We need to check if each node is within the its bounds. The left child has to be within (-inf, parent), right child has to be within (parent, inf)

Algo:
define util function with root, left_bound, right_bound for params as follows
- If not root, return True
- If not within value bounds, return False
- Return OR of recursive call for left and right child, right_bound is parent for left subtree call, left_bound is parent for right subtree call

  • call util function over root with bounds as (-inf, inf)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Same tree
Recursive algorithm: - if not p and not q, return True - if values not equal or not p or not q, return False - return AND of recursive calls of left subtree and right subtree Iterative algorithm: - Use stack, put (p, q) in stack - while stack - pop - if not p and not q, continue - if values not equal or not p or not q, return False - stack append((p.left, q.left)) and append((p.right, q.right)) - end while -return True
26
Symmetric tree
Recursive algorithm: - define util function with l_tree and r_tree for params as follows - if not l_tree and not r_tree, return True - if values not equal or not l_tree or not r_tree, return False - return AND of recursive calls of on (l_tree.left, r_tree.right) and (l_tree.right, r_tree.left) Iterative algorithm: - Use stack, put (l_tree, r_tree) in stack - while stack - pop - if not l_tree and not l_tree, continue - if values not equal or not l_tree or not r_tree, return False - stack append((l_tree.left, r_tree.right)) and append((l_tree.right, r_tree.left)) - end while -return True
27
Binary tree level order traversal
Recursive algo: - define answer as [] - define dfs with node and depth as params - if not node, return None - if len(answer) equals depth, answer.append([]) - answer[depth].append(node.val) - dfs(node.left, depth + 1) - dfs(node.right, depth + 1) call dfs(root, 0) return answer Iterative algo: - Define answer as [] and deque - put root in deque - while queue: - get queue length and define level as [] - for i till queue_length - ele = queue.popleft() - if ele, then append left and right to queue and append ele.val to level - end for - if level, append level to answer - end while return answer
28
Convert sorted list to binary search tree
Idea: We need to find a middle, and then split from there. The left part of list will be the left subtree, and right part will be right subtree Algorithm: - Define getMiddle function with node as param as follows - define fast and slow as head and prev as none - while fast and fast.next, assign fast = fast.next.next, prev = slow, slow = slow.next - if prev, then prev.next = None - return slow In main function: - if not head, return None - if not head.next, return TreeNode(head.val) - middle = getMiddle(head) - root = TreeNode(middle.val) - root.right = recursive call(middle.next) - root.right = recursive call(head) - return root
29
Populating next right pointers
Idea: Similar to BFS. Need to assign the next pointer to the next node in the traversal. Iterative algo: - if not root, return root - define queue and append root - while queue - get queue length - for i till queue length - node = popleft - if node - if i is queue length - 1, then node.next = None - else node.next = queue[0] - append node.left and node.right to the queue - end for - end while -return root Recursive algo: - Define a dictionary depth_dict - Define a dfs function with node and depth as params as follows - if not node, return - if depth not in depth_dict, depth_dict[depth] = node - else depth_dict[depth].next = node, depth_dict[depth] = node - call dfs(node.left, depth + 1) and dfs(node.right, depth + 1) - call dfs(root, 0) - return root
30
Best time to buy and sell stock
Idea: We need to iteratively find the minimum price at which the stock can be bought and then continue to find the max_profit Algorithm: - Define max_profit as 0 and min_price as float('inf') - iterate through the prices - if current price less than the min_price, then assign current price to min_price - else calculate max_profit using max between the current value and (current price - min_price) - end iterate -return max_profit
31
Number of islands
Idea: We need to use a graph traversal teechnique to find the continuous block of land cells, mark them visited and append the answer count BFS solution: - Define bfs function with row, col as params as follows - define a deque, add (row, col) to the queue and visited set - define 2d directions array for 4 directions - while queue - pr, pc = popleft() - for each direction - calculate final position from popped pr, pc - if that position is in bounds and is a land and not in visited - append that position to the queue and add it to visited array - end if - end for - end while - Define m, n, empty visited set and answer as 0 - for i till m - for j till n - if (i, j) is land and not in visited - run bfs on (i, j) and increment the answer count
32
Course schedule
Idea: We run dfs on the course - prerequisite relationship graph, and if we encounter cycle, then their is cyclic dependency, thus not possible to finish the course DFS solution: -Define map like { i: [] for i in range(numCourses) } and an empty visited set -add the prereqs in the above define map -define dfs function with course as a parameter as follows -if course in visited, return False -if prereq of course is empty, return True -add course to visited -for every prereq in course prereqs -if not dfs(prereq), return False -end if -end for -remove course from visited -assign [] to map of that course to avoid recomputation -return True -end func -iterate through numcourses: -if not dfs, return False -end if -end iterate -return True
33
Course schedule 2
Idea: Topological sort, dfs to fist add prerequisites and then others Algorithm: (Cycle set in this code is same as visited set in course schedule 1, visited set to track whether the course has been added to output or not) -Define the prereq map like this { c: [] for c in range(numCourses)} -Add the course and prereq to the prereq map -declare output as empty list and visited and cycle as empty set -define dfs with course param as follows -if course in cycle, return False -if course in visited, return True -add course to cycle set -for each pre of prereq[course] -if not dfs(pre), return False -end for -remove course from cycle -add course to visited -append course to output -for each course number -if not dfs, return [] -end for -return output
34
Min Stack
Idea: We need to maintain the min element in the stack at each point of it So the option is to have another stack called min_stack Solution: During push, push the minimum of the value and the current top of min-stack to the min_stack
35
LRU cache
Idea: We will use hashmap and a doubly linked list. Hashmap will be (key, node pointer). And we will have dummy right and left pointers to keep track of the most recent and least recent nodes respectively Solution: -Declare Node class with key, val, prev and next 1. INIT -initialize capacity and empty hashmap -intialize dummy pointers right and left and link them to each other in the beginning 2. Define utility function insert for inserting node to the right 3. Define utility function for removing the node by delinking it from its prev and next nodes 4. GET -if key in map -remove that node -insert that node -return the value -end if -return -1 5. PUT -if key in map -remove that node -end if -assign new node to that key in map -insert that node -if map len > capacity -remove lru, i.e. left.next -delete the key from hash map -end if
36
Implement trie (prefix tree)
-Define TrieNode class with children as hashmap and endOfWord boolean as False 1. INIT -initialize root as TrieNode() 2. INSERT -define curr as root -for every char in word -if char not in curr.children -curr.children[c] = TrieNode -end if -curr = curr.children[char] -end for -mark curr.endOfWord = True 3. SEARCH -define curr as root -for every char in word -if char not in curr.children, return False -end if -curr = curr.children[char] -end for -return curr.endOfWord 4. STARTS WITH -same as SEARCH, just return True instead of endOfWord
37
Design add and search words data structure
Idea: Use Trie to store the words data Use dfs to search the word since there might be wildcard characters Solution: -Define TrieNode class with children as empty hashmap and endOfWord boolean as False 1. INIT -initialize root as TrieNode() 2. ADD WORD -define curr as root -for every char in word -if char not in curr.children -curr.children[char] = TrieNode() -end if -curr = curr.children[char] -end for -curr.endOfWord = True 3. SEARCH -define dfs function with j and root as param as follows -curr = root -for i from j to len(word) -char = word[i] -if char is '.' -for every child in children -if dfs(i + 1, child), return True -end if -end for return False -end if -else -if char not in children, return False -end if curr = curr.children[char] -end else -return curr.endOfWord -return dfs(0, self.root)
38
Longest increasing subsequence
Idea: We start from the end of the array, and then compare the current element to every element after it, and compute LIS using the already stored LIS of elements further in the array Algorithm: -Define lis array of length nums n -for i from n-1 to 0 -for j from i + 1 to n - 1 -if nums[i] < nums[j] -lis[i] = max(lis[i], 1 + lis[j]) -end if -end for -end for -return max from lis array
39
Pacific atlantic water flow
Idea: Instead of starting from the land grid, we start from the borders, and find which cells can flow into that ocean. We maintain two sets for each ocean and then find the intersection Algorithm: -Declare empty sets for both pacific an atlantic oceans -declare dfs with row, col, visited set and prev_height as params as follows -if (row, col) in visited set or out of bounds of heights[row][col] < prev_height, return -end if -add (r, c) to visited set -call dfs on its four neighbors and pass the height of (r, c) as param for prev_height -call dfs for each cell bordering the oceans -find the cells common in both the sets and add them to an answer array -return answer
40
Diameter of binary tree
Algorithm: -Define self.result as 0 -define dfs function with node as param as follows -if not node, return 0 -define left_height and right_height as recursive calles to node.left and node.right -set result as max between itself and (left_height + right_height) -return 1 + max(left_height, right_height) -dfs(root) -return self.result
41
Reorganize string
Idea: Use heap and start with the most occurring characters, at each iteration Algorithm: -create hashmap of char counts Counter like count = Counter(s) -construct max_heap = [[-cnt, char] for char, cnt in count] -heapq.heapify(max_heap) -while max_heap or prev -if prev and not max_heap, return "" -cnt, char = heappop -answer += char -cnt += 1 -if prev, then heappush(prev), prev = None -if cnt < 0, prev = [cnt, char] -end while -return answer
42
Game of life
Idea: To convert the board in place, we need to find a way to encode the current positions to use it and calculate next state We will use following Original | New | State(encoding) 0 | 0 | 0 1 | 0 | 1 0 | 1 | 2 1 | 1 | 3 Algorithm: -define countNeighbours function with r and c params as follows -declare neighbours = 0 -for i from r + 1 to r + 2 -for j from c + 1 to c + 2 -if (i == r and j == c) or i < 0 or j < 0 or i == rows or j == cols, continue -if board[r][c] is 1 or 3, neighbours += 1 -end for -end for -return neighbours -for all rows -for all cols -neighbours = countNeighbours(i, j) -if board[i][j] == 1 -if neighbours is 2 or 3, board[i][j] = 3 -end if -elif neighbours is 3, board[i][j] = 2 -for all rows -for all cols -if board[i][j] == 1, board[i][j] = 0 -elif board[i][j] is 2 or 3, board[i][j] = 1
43
Minesweeper
Idea: For an empty square without any adjacent mines, we need to recursively call the function, i.e. simulate clicks on its neighbours Algorithm: -Define utility function numMines with board, x and y for params as follows -num_mines = 0 -for r from x - 1 to x + 1 -for c from c - 1 to c + 1 -if in bounds and (r, c) is mine, inc num_mines -end for -end for -return num_mines -if not board, return board -x, y = click -if (x, y) is mine, assign 'X' to (x, y) -else -num_mines = numMines(board, x, y) -if num_mines, assign str(num_mines) at (x, y) -else -assign 'B' to (x, y) -for r from x - 1 to x + 1 -for c from y - 1 to y + 1 -if r and c in bounds and (r, c) not 'B', call self with board and [r, c] as params -end for -end for -end if else -end if else -return board
44
Design tic-tac-toe
Idea: One way, create a board, and then mark each position as 'X' or 'O'. Then at every move, check the row, column and the diagonal in question. Better way, assign -1 and 1 to two player moves, keep adding the move value to the corresponding row, column and diagonal, and if it ever becomes equal to n, we have the winner Solution: 1. INIT -declare rows and columns as defaultdict(int) -declare left_diag, right_diag and n as 0,0 and n respectively 2. MOVE -number is -1 if player is player 1 else 1 -self.rows[row] += number -self.columns[col] += number -if row == col, self.left_diag += number -if row + col == self.n - 1, self.right_diag += 1 -if max(abs(self.rows[row]), abs(self.columns[col]), abs(self.right_diag), abs(self.left_diag)) == self.n, return player -return 0
45
Graph valid tree
Idea: Recursive dfs to see if there are cycles. Maintain a visited array and check if its length equals n (To check if all nodes are connected) Algorithm: -if not n, return True (No nodes is also a graph) -create adjacency list as adj = {i: [] for i in range(n)} -fill in adjacency list -declare visited set -define dfs function with i and prev for params as follows -if i in visited, return False -add i to visited -for every j in adj[i] -if j == prev, continue -if not dfs(j, i), return False -end for -return True -return dfs(0, -1) AND n == len(visited)
46
Reverse bits
Idea: -We use bitwise AND, bitwise OR and bitwise SHIFTS to extract each of the 31 bit and then reverse it Algorithm: -declare answer as 0 -for i till 31 -extract bit as bit = (n >> i) & 1 -push the bit to left and OR with answer as answer = answer | (bit << (31 - i)) -end for -return answer
47
Sum of two integers
* IN JAVA Idea: At the bit level, result of & is one only if one of the bits is 1. This can be done using ^. For the carry, we can use & and then left shift it once. Keep doing this until we don't have a carry Algorithm: -while b is not 0 -int carry = (a & b) << 1 -a = a ^ b -b = carry -end while -return a
48
Word break
Idea: Bottom Up DP. We start with the end character, then one my one check if any word fits, and then store True in the cache at that position. Eventually, we will have the result at 0th position Algorithm: -Declare dp array with Falses for len(s) + 1 -Assign True to last position of dp cache -for i from len(s) - 1 to 0 -for every word in wordDict -if i + len(w) <= len(s) and s[i:i + len(w)] == w, dp[i] = dp[i + len(w)] -if dp[i], break (break coz one word already fits the above condition) -end for -end for -return dp[0]
49
Spiral matrix
Idea: Fix the left right top and bottom boundaries, and then print in for loops while the left < right and top < bottom Algorithm: -declare empty answer array -declare left and right as 0 and len(matrix[0]) -declare top and bottom as 0 and len(matrix) -while left < right and top < bottom -for i range (left, right), append [top][i] to answer -top += 1 -for i range (top, bottom), append [i][right - 1] to answer -right -= 1 -if not (left < right and top < bottom), break -for i range (right - 1, left - 1, -1), append [bottom - 1][i] to answer -bottom -= 1 -for i range (bottom - 1, top - 1, -1), append [i][left] to answer -left += 1 -end while -return answer
50
Number of connected components in an undirected graph
Idea: Build an adjacency list and then run dfs through each node. Maintain a visited set to track the connected components Algorithm: -if n is 1, return 1 -declare answer as 0 -declare adjacency list as adj = {node: [] for node in range(n)} -build adjacency list using edges both ways (n1->n2) and (n2->n1) -declare empty visited set -declare dfs function with node for param as follows -for every neighbor of node -if neighbor not in visited -add neighbor to visited and call dfs(neighbor) -end if -end for -end func -for node in adjacency list -if node not visited -add node to visited -inc num_components -call dfs(node) -end if -end for -return num_components
51
Valid anagram
Algorithm: -check length and return False if unequal -define counter array for 26 alphabets -iterate and add 1 in position for char in s, subtract 1 for char in t simultaneously -iterate through counter and return False if value not 0 -return True
52
Group anagrams
Idea: -group the strings into dictionary based on the char counts Algorithm: -define answer as defaultdict(list) -for every string in strs: -counter = [0] * 26 -for every char in string: -counter[char] += 1 -end for -answer[tuple(counter)].append(string) -end for -return list(answer.values())
53
Top k frequent elements
Idea: One way is to store frequency in a dictionary, then sort it using the frequency and pick first k ones Second way is using heap Algorithm: -declare and define the counts dictionary -for every entry in dictionary -push into heap -if heap length > k, pop from the heap -end for -loop k times and pop from heap and append the number to the answer -return answer
54
Encode and decode strings
Idea: -encode along with length and an identifier like "#" Solution: 1. ENCODE -initialize result as string -for every s, append len(s) + "#" + s to the result -return s 2. DECODE -initialize res and i as [] and 0 respectively -while i < len(s) -j = i -while s[j] != "#" -j += 1 -end while -length = int(s[i : j]) -res.append(s[j + 1, j + 1 + length]) -i = j + 1 + length -end while -return res
55
Product of array except self
Idea: Calculate prefix product and then postfix product Algorithm: -prefix = 1 and answer = [] -for every number -answer.append(prefix) and prefix *= nums[i] -end for -postfix = 1 -for every number in reverse -answer[i] *= postfix and postfix *= nums[i] -end for -return answer
56
Longest consecutive sequence
Idea: Create a set of the given array and check if the number + 1 is present for the current number. Increase seq length if there is Algorithm: -if not nums, return 0 -num_set = set(nums) -max_seq = 1 -for number in num_set -if number - 1 not in num_set -curr_seq = 1 -while (number + 1) in num_set -curr_seq += 1 and number += 1 -end while -reassign max_seq -end if -end for -return max_seq
57
Valid palindrome
Idea: Start with l and r pointers, and check if the chars are equal Algorithm: -init l and r to 0 and len - 1 -while l < r -while l < r and s[l] not alphanum, l += 1 -while l < r and s[r] not alphanum, r -= 1 -if s[l].lower() != s[r].lower(), return False -inc l and dec r -end while -return True
58
Container with most water
Idea: We start with left and right pointers, calculate the max volume while moving them closer based on the height comparison Algorithm: -initialize l, r and max_volume -while l < r -calculate current volume and reassign max_volume -if height at l <= r, inc l -else dec r -end if else -end while -return max_volume
59
Longest substring without repeating characters
Idea: Two pointer approach. One way is to remove the l characters from the set and inc l until there r character is not it it. Then add r char to set and calculate result every iteration Another way is similar, but we store the position of the r char in map and calculate the length based on that Solution 1: -initialize l, charset, max_len -for r in range length -while r char not it charset -remove l char from set -inc l -end while -add r char to set -reassign max_len -end for -return max_len Solution 2: -intialize l, charmap, max_len -for r in range length -if char at r already in map -assign l = max(charmap[s[r]] + 1, l) -end if -charmap[s[r]] = r -reassign max_len -end for -return max_len
60
Longest repeating character replacement
Idea: We maintain a hashmap of frequencies. And we only replace characters within the window which are not the most frequent Algorithm: -initialize map, answer and left -for right in range length -map[right] += 1 -while (r - l + 1) - max(map.values()) > k: -dec map[left] -inc left -end while -answer is max between itself and (r - l + 1) -end for -return answer
61
Find minimum in rotated sorted array
Idea: Standard binary search, we just move the pointers based on if we are in the correctly sorted subarray Algorithm: -answer = nums[0] -init left and right pointers -while left <= right -if nums[left] < nums[right] -answer = max(answer, nums[left]) -break -end if -calculate mid -answer = max(answer, nums[mid]) -if nums[mid] >= nums[left], left = mid + 1 -else, right = mid - 1 -end if else -end while -return answer
62
Search in rotated sorted array
Idea: Find whether we are in left sorted or right sorted array and based on that, change the left or right pointers Algorithm: -initialize left and right pointers -while left <= right -mid = (left + right) // 2 -if target is at mid, return mid -end if -if left <= mid -if target > mid or target < left, left = mid + 1 -else right = mid + 1 -end if else -else -if target < mid or target > right, right = mid + 1 -else left = mid + 1 -end if else -end if else -return -1
63
Reorder list
Idea: Use slow and fast pointer to find the middle part of the list De link that and then reverse the 2nd list Then merge them
64
Remove nth node from end of list
#NAME?
65
Lowest common ancestor of a binary search tree
#NAME?
66
Kth smallest element in a BST
Idea: Inorder traversal and then return the kth element Algorithm: -init n, stack and curr as 0, [] and root respectively -while curr or stack: -while curr, append curr to stack and curr = curr.left -end while -curr = stack.pop() -inc n -if n = k, return curr.val -end if -curr = curr.right -end while
67
Construct binary tree from preorder and inorder traversal
Idea: Find the root index in the inorder traversal, i.e index of first element in preorder and then recursively call the method on the array splits Algorithm: -if not preorder or inorder, return None -end if -root_index = inorder.index(preorder[0]) -root = Node(preorder[0]) -root.left = call(preorder[1 : root_index + 1], inorder[: root_index]) -root.right = call(preorder[root_index + 1 :], inorder[root_index + 1 :]) -return root
68
Clone graph
Idea: Create a map of old to new node and then recursively append the copy of each nodes neighbors Algorithm: -define node_map as {} -define dfs function with node for param as follows -if node in node_map, return node_map[node] -end if -copy = Node(node.val) -node_map[node] = copy -for each neighbor of node -copy.neighbors.append(dfs(neighbor)) -end for -return copy -end func -return dfs(node) if node else return None
69
Graph valid tree
Idea: Build an adjacency list. Use a visited set to recursively check for cycles. Valid tree if no cycle and length of set equal to number of nodes (cause disconnected nodes) Algorithm: -if not n, return True (coz empty graph is still valid tree) -build adjacency list in form of dict(i, [neighbors]) and define visited set -define dfs function with i and prev for param as follows -if i in visited, return False -end if -add i to visited -for every j in adj[i]: -if j is prev, continue -end if -if not dfs(j, i), return False -end if -end for -return True -end func -return dfs(0, -1) AND n == len(visited)
70
Number of connected components in an undirected graph
Idea: Use dfs and visited set to track connected nodes for one node Algorithm: -if n is 1, return 1 -init number of components as 0, empty visited set and generate adjacency list -define dfs function with node for param as follows -for each neighbor in adj list of node -if neighbor not visited -add neighbor to visited -dfs(neighbor) -end if -end for -end func -for each node in adj list -if node not in visited -add node to visited -inc number of components -dfs(node) -end if -end for -return number of components`
71
Climbing stairs
Algorithm: -Init dp array of length n -if i is 0, dp[0] is 1 -else if i is 1, dp[1] is 2 -else, dp[i] = dp[i - 1] + dp[i - 2] -end else if -return dp[n - 1]
72
House robber
Algorithm: -init rob1 and rob2 as 0 -for i in range(n) -temp = max(rob1 + nums[i], rob2) -rob1 = rob2 -rob2 = temp -end for return rob2
73
House robber 2
Idea: We run the house robber 1 for the array without the first element and the array without the last element. And then return the maximum Algorithm: -define helper function of house robber 1 -return max(nums[0], helper(nums[1:]), helper(nums[:-1])) ......(nums[0] to handle the case where we only have array of size 1)
74
Palindromic substrings
Idea: Same as the longest palindromic substring problem, but instead of storing the max result, we increment the count Algorithm: -define helper function to calculate the number of palindromic substrings within the given string with left and right as the params, and return the number of palindromic substrings from it -init result as 0 -for i in range(len(s)) -result += helperfunc(i, i) ...... (for odd length strings) -result += helperfunc(i, i + 1) ...... (for even length strings) -end for -return result
75
Decode ways
Algorithm: -init cache = { len(s): 1 } -for i in range len(s) - 1 to 0 -if s[i] is 0, cache[i] = 0 -else cache[i] = cache[i + 1] -end if else -if i + 1 in bound AND (s[i] is "1" OR (s[i] is 2 AND s[i + 1] is in "0123456")) -cache[i] += cache[i + 2] -end if -end for -return cache[0]
76
Coin change
Idea: For each coin, decode ways is 1 + amount - coin Algorithm: -initialize dp array of length amount + 1 with the same amount + 1 values -dp[0] = 0 -for i from 1 to amount -for each coin c -if i - c >= 0 -dp[i] = min of itself and (1 + dp[i - c]) -end if -end for -end for -return dp[amount] if dp[amount] not default value else return -1
77
Maximum product subarray
Algorithm: -init answer as max(nums) -init curr_max and curr_min both as 1 -for every number in nums -if number is 0 -reassign curr_max and curr_min to 1 -continue -end if -temp = curr_max * number -curr_max = max(curr_max * number, curr_min * number, number) -curr_min = min(temp, curr_min * number, number) -answer = max(answer, curr_max) -end for -return answer
78
Word break
Algorithm: -init n as len(s) -init dp array of Falses of length n + 1 and assign dp[n] as True -for i from n - 1 to 0 -for every word in wordDict -if dp[i] -return True -end if -if (i + len(word)) <= n and s[i : i + len(word)] is word -dp[i] = dp[i + len(word)] -end if -end for -end for -return dp[0]
79
Unique paths
Idea: Store the number of unique paths for each cell in the grid Algorithm: -init dp array of m*n with all 0s -for i in range m -for j in range n -if i is 0 or j is 0 -dp[i][j] = 0 -else dp[i][j] += dp[i - 1][j] + dp[i][j - 1] -end else if -end for -end for -return dp[m - 1][n - 1]
80
Longest common subsequence
Idea: Create a p matrix and store the longest sequence length up until that point Algorithm: -initialize m and n as length of text1 and text2 respectively -create dp array of 0s of dimensions (m + 1) * (n + 1) -for i in range 1 to m -for j in range 1 to n -if text1[i - 1] == text2[j - 1] -dp[i][j] = 1 + dp[i - 1][j - 1] -else -dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) -end if else -end for -end for -return dp[m][n]
81
Maximum subarray
Idea: We use sliding window type approach. Once the current sum becomes -be, we reset the start of window to current one -Algorithm: -init curr_sum as 0 and max_sum as nums[0] -for every number in nums -if curr_sum < 0, curr_sum = 0 -end if -curr_sum += number -max_sum = max(max_sum, curr_sum) -end for -return max_sum
82
Insert interval
Idea: Iterate through the intervals and add wherever it fits Algorithm: -init answer as empty list -for every interval i -if new end < i start, append new interval and return answer + intervals[i:] -elif new start > i end, append interval i -else new interval = [min(new start, i start), max(new end, i end)] -end if else -end for -append new to answer -return answer
83
Non overlapping intervals
Idea: Keep track of the end and increment count based on the minimum end value if the intervals overlap Algorithm: -init answer as 0 and prev_end as intervals[0][1] -for every start, end of interval after 1st -if start >= prev_end -prev_end = end -else -answer++ -prev_end = min(prev_end, end) -end if else -end for -return answer
84
Meeting rooms
Algorithm: -intervals.sort() -for every interval after first -if current interval start < prev interval end -return False -end if -end for -return True
85
Meeting rooms 2
Idea: Store the start and end times in seperate array and sort them And based on which is smaller, increment count for number of meetings currently going on Algorithm: -start = sorted([i[0] for i in intervals]) -end = sorted([i[1] for i in intervals]) -init answer, count, s and e to 0 -while s < length -if start[s] < end[e] -inc s and count -else -inc e and dec count -end if else -answer = max(answer, count) -end while -return answer
86
Rotate image
Idea: Set the l, r, top and bottom boundaries and swap the elements Algorithm: -set l and r to 0 and length of matrix - 1 respectively -while l < r -for i in range (r - l): -declare top and bottom are same as l and r respectively -top_left = matrix[top][l + i] -matrix[top][l + i] = matrix[bottom - i][l] -matrix[bottom - i][l] = matrix[bottom][r - i] -matrix[bottom][r - i] = matrix[top + i][r] -matrix[top + i][r] = top_left -end for -inc l and dec r -end while
87
Spiral matrix
Idea: Set the l, r, t, b boundaries and iterate through the edges one by one We set bottom and r boundaries outside the bounds Algorithm: -declare empty answer array -declare l and r as 0 and len(matrix[0]) respectively -declare top and bottom as 0 and len(matrix) respectively -while l < r and top < bottom: -for i between (l, r) -append matrix[top][i] -top += 1 -end for -for i between (top, bottom) -append matrix[i][r - 1] -r -= 1 -end for -if not (l < r and top < bottom) -break -end if -for i between (r - 1, l - 1, -1) -append matrix[bottom - 1][i] -bottom -= 1 -end for -for i between (bottom - 1, top - 1, -1) -append matrix[i][l] -l += 1 -end for -end while -return answer
88
Set matrix zeroes
Idea: Store whether the row or column needs to be zeroed in a boolean array Algorithm: -declare m and n -declare rows and cols array as [False] * m and [False] * n respectively -iterate through matrix -if [i][j] is 0, set rows[i] and cols[j] to True -end iterate -iterate though matrix -if rows[i] or cols[j] -set [i][j] to 0 -end if -end iterate
89
Number of 1 bits
Idea: Either you mod by 2 until number isn't zero Another way, in binary terms, n - 1 has the rightmost 1 replaced by zero and all the other bits to the right as 1. So logic ANDing the two eliminates one 1. e.g. 100000 - 1 = 011111 Algorithm: -init answer as 0 -while n -n = n & (n - 1) -answer += 1 -end while -return answer
90
Counting bits
Idea: Look at the pattern of bits. Once the power of 2 is obtained, the number of bits is 1 + the previous combination Algorithm: -init answer array of size n + 1 with 0s -init offset as 1 -for i in range(1, n + 1) -if i == offset * 2, -offset = i -end if -answer[i] = 1 + answer[i - offset] -end for -return answer
91
Reverse bits
Idea: One way to extract LSB is to & the number with 1. Same way, we can shift the number to extract other bits. Then we can shit this bit to left and then| with 0 or answer Algorithm: -init answer as 0 -for i in range(32) -bit = (n >> i) & 1 -answer = answer | (bit << (31 - i)) -end for -return answer
92
Missing number
Idea: Either using sum of n integers formula or just keep xoring the i and nums[i] and the number at the end is the missing number(xor the two same values results in 0) Algorithm: -init answer as n -for i in range(n) -answer ^= i ^ nums[i] -end for -return answer