Algorithms
-
Array Duplicates:
Given an array of n elements which contains elements from 0 to n-1, with any of these numbers appearing any number of times. Find these repeating numbers in O(n) and using only constant memory space.- Mathematical Solution: \(O(n), O(1)\)
- Traverse the given array from i= 0 to n-1 elements
- Go to index arr[i]%n and increment its value by n.
- Now traverse the array again and print all those
- indexes i for which arr[i]/n is greater than 1.
- Traverse the given array from i= 0 to n-1 elements
- Indexes Solution: \(O(n), O(1)\)
traverse the list for i= 0 to n-1 elements { check for sign of A[abs(A[i])] ; if positive then make it negative by A[abs(A[i])]=-A[abs(A[i])]; else // i.e., A[abs(A[i])] is negative this element (ith element of list) is a repetition }
- Mathematical Solution: \(O(n), O(1)\)
- Re-Arranging Array Indexes:
Rearrange an array so that arr[i] becomes arr[arr[i]] with O(1) extra space- Mathematical Solution: \(O(n), O(1)\)
- Increase every array element arr[i] by \((\text{arr}[\text{arr}[i]] % n) * n\).
- Divide every element by \(n\).
The idea is to store both numbers as the quotient and the remainder inside the array element
- Mathematical Solution: \(O(n), O(1)\)
- Two Sum Problem:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.- HashTable: \(O(n), O(1)\)
Iterate and inserting elements into the table, we also look back to check if current element’s complement already exists in the table. If it exists, we have found a solution and return immediately.
- HashTable: \(O(n), O(1)\)
-
Permutations of an Array:
Key Idea:def _permute(a, l, r, results): if l==r: results.append(a.copy()) else: for i in range(l,r+1): a[l], a[i] = a[i], a[l] _permute(a, l+1, r, results) a[l], a[i] = a[i], a[l] def permute(arr: List[int]) -> List[List[int]]: results = [] _permute(arr, 0, len(arr)-1, results) return resultsFor strings:
def _permute(s, chosen, results): if len(s) < 1: # results.append(a.copy()) print(chosen) else: for i in range(len(s)): # Choose c = s[i] chosen += c s = s.replace(c, "") # Explore _permute(s, chosen, results) # UnChoose chosen = chosen[:-1] s = s[:i] + c + s[i:] def permute(s): results = [] _permute(s, "", results) return results permute('abc')Generate permutation at index \(k\):
def getPermutation(self, n, k): """ :type n: int :type k: int :rtype: str """ k-=1 nl = list(range(1,n+1)) out = '' while n>0: temp = math.factorial(n-1) out+=str(nl.pop(k//temp)) k %= temp n -= 1 return out - Hight/Depth of Tree:
Use DFS:def dfs(self, root, visited = [], depth=1): if not root.children: return depth # visited.append(root) max_depth = depth for node in root.children: # 2 Lines below: only needed if graph is not a tree # if node not in visited: # max_depth = max(self.dfs(node, visited, depth+1), max_depth) max_depth = max(self.dfs(node, depth+1), max_depth) return max_depth def maxDepth(self, root: 'Node') -> int: if not root: return 0 return self.dfs(root) - Pre-Order Traversal:
def preorderTraversal_iterative(self, root: TreeNode) -> List[int]: arr = [] stack = [] while 1: while root: stack.append(root) arr.append(root.val) root = root.left if not stack: break root = stack[-1].right stack.pop() return arr def preorderTraversal_recursive(self, root: TreeNode) -> List[int]: self.arr = [] def helper(root): if not root: return self.arr.append(root.val) helper(root.left) helper(root.right) helper(root) return self.arrIn-order:
def inOrderT(root): self.ans = [] def helper(root): if not root: return helper(root.left) self.ans.append(root.val) helper(root.right) helper(root) return self.ans
Strings
- Uniqueness of characters:
- Array of indices / Hashmap: O(n=len(string)), O(256)
- Permutations (str a is perm of str b):
- Sort both -> equality: O(n log n)
- (fixed) array of character counts
- Replace a char in str w/ more than one char (e.g. all ‘a’ in str -> ‘bb’):
- count number of ‘a’ in str -> multiply by (len(‘bb’) - 1) -> start modifying from back of string (backwards)
- Palindrome:
To check for if a string is a Palindrome, count the number of characters:- even len(s): all char-counts must be even
- odd len(s): only one char-count can be odd
Best sol (Still O(N)):
- Use a bit vector -> map chars to 26 bit-vector -> toggle everytime you see char -> check bit vector == 0 (has at most 1 “on” bit)
-
Q1.5:
-
Rotate Matrix (implement it):
- Check str a is ROTATION of str b:
By making one call to isSubstring:- Note: str b always substring of str a+a (e.g. “waterbottle”, “erbottlewat”: “erbottlewat” isSubstr of “waterbottle”+”waterbottle”=”wat_erbottlewat_erbottle”)
- Notes:
- Ask ASCII or UTF8
NOTES
- Learn about how to handle cycles in arrays in O(1) space
- For Recursion: Ask the size of the input (i.e. would it fit in the stack?) else iterative solution
-
Interviewing at GOOGLE:
Prove the Resume
White board
Make sure the interviewer Feels comfortable working with you on the team
Ask a lot of questions; the interviewer is vague on purpose: what are the time&space constraints?
Keep Thinking
Keep the interviewer happy and attentive
Have a very positive/approachable attitudeData Structures, Algorithms, Space&Time Complexity
System Design, OOP,Dijkstra, A*, DFS, BFS, Tree, traversal,
NP-Complete, NapSack, Traveling Salesman, NP-Completeness, Discrete Math, Counting (n choose k problems),
Recursion: iterative to recursive, complexity
OS: processes, threads, concurrency issues, locks etc., resource allocation, context switching, scheduling
System Design: feature sets, interfaces, class hierarchies, distributed systems, constrained system design
The Internet: routers, servers, search, DNS, firewallsTesting Experience, Unit Tests, Interesting Test-cases, integration Tests for Gmail?
C++, Java, Python, GoLang
- GOOD LINK
- Fellowship Program in ML
- Listen Carefully
- Draw an example
- Find Bruteforce
- Optimize:
- look for unused info - more examples - start with “incorrect” sol - timeVSspace - precompute - BCR
- Walk through the algorithm
- Implement
- Test
- Arrays and Strings questions are interchangeable
Face-up/Face-down Cards:
Video
- A card deck of 52 cards, 13 face-up.
- The Face-up cards are distributed randomly throughout the deck.
- You are blindfolded and you don’t know anything about the cards.
- How can you create two piles with the same amount of face-up cards?
Let \(x\) be the number of face-up cards in pile #1
| \(\uparrow\) | \(\downarrow\) | |
| pile #1 \(= 13\) | \(x\) | \(13 - x\) |
| pile #2 \(= 39\) | \(13 - x\) | \(26 + x\) |
Face-up/Face-down Cards Generic Version:
- A card deck of 52 cards, \(k\) face-up.
Let \(x\) be the number of face-up cards in pile #1
| \(\uparrow\) | \(\downarrow\) | |
| pile #1 \(= k\) | \(x\) | \(k - x\) |
| pile #2 \(= 52-k\) | \(k - x\) | \((52-k) - (k-x)\) |
Face-up/Face-down Cards Generic Version (flipped):
- A card deck of 52 cards, \(k\) face-down.
- How can you create two piles with the same amount of face-down cards?
Let \(x\) be the number of face-down cards in pile #1
| \(\uparrow\) | \(\downarrow\) | |
| pile #1 \(= k\) | \(k-x\) | \(x\) |
| pile #2 \(= 52-k\) | \((52-k)-(k-x)\) | \(k - x\) |