Reverse a binary tree
# recursively
def invertTree1(self, root):
if root:
root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
return root
# BFS
def invertTree2(self, root):
queue = collections.deque([(root)])
while queue:
node = queue.popleft()
if node:
node.left, node.right = node.right, node.left
queue.append(node.left)
queue.append(node.right)
return root
# DFS
def invertTree(self, root):
stack = [root]
while stack:
node = stack.pop()
if node:
node.left, node.right = node.right, node.left
stack.extend([node.right, node.left])
return rootInorder traversal binary tree
DFS
left, root, right
Preorder binary tree
DFS
root, left, right
Postorder binary tree
DFS
left, right, root
What are collisions in a hash map
This scenario can occur because according to the equals and hashCode contract, two unequal objects in Java can have the same hash code.
It can also happen because of the finite size of the underlying array, that is, before resizing. The smaller this array, the higher the chances of collision.
That said, it’s worth mentioning that Java implements a hash code collision resolution technique which we will see using an example.
Keep in mind that it’s the hash value of the key that determines the bucket the object will be stored in. And so, if the hash codes of any two keys collide, their entries will still be stored in the same bucket.
And by default, the implementation uses a linked list as the bucket implementation.
The initially constant time O(1) put and get operations will occur in linear time O(n) in the case of a collision. This is because after finding the bucket location with the final hash value, each of the keys at this location will be compared with the provided key object using the equals API.
To simulate this collision resolution technique, let’s modify our earlier key object a little:
level order traversal of a binary tree
BFS
bubble_sort
insertion sort
O n^2, constant space
selection sort
O n^2, constant space
merge sort
time: o(n*log(n))
space: O(N), if we have 16 objects in arr, we go 16 -> 8 -> 4 -> 2 -> 1, 2 needs both 1’s to solve, 4 needs both 2s, until we get up to 16 which needs both 8s, so it evaluates to N space, it would be NLogN if we evaluated all the branches at the same time. https://stackoverflow.com/questions/10342890/merge-sort-time-and-space-complexity
def merge_sort(self, arr):
heap sort
time: o(n*log(n)), worst O n^2
space: constant space since we only re-arrange the initial list (or heap)
quick sort
time: O n*log(n)
space = log(n)
def quick_sort(self, arr, low, high):
reverse a linked list
def reverse_iterative(self):
add, insert after a node, delete, find a node in a linked list
class Node(object):
def find(target, node):
def insert_after(after, new_node, node):
class LL:
need a reference to head to delete a node, since we could delete the first node!
add, insert after a node, delete, find a node in a doubly-linked list
class ListNode:
class MyLinkedList:
add, insert after a node, delete, find a node in a circular-linked list
make sure you do head/next
have a head pointer similar to the other problems where we start off with head.next as the head, the pointer is just a 0 value node that helps with the list
instead of while cur.next, use cur.next != head to know we’ve made a loop
insert/add indexes can be greater than the length of the list. a list of len 3 and we insert on index 3 is okay bc we just add to the end.
subset, subarray, subsequence
base: [1, 2, 3, 4]
A subarray is a CONTIGUOUS part of array.
An array that is inside another array. For example, consider the array [1, 2, 3, 4], There are 10 non-empty sub-arrays. The subarrays are (1), (2), (3), (4), (1,2), (2,3), (3,4), (1,2,3), (2,3,4) and (1,2,3,4). In general, for an array/string of size n, there are n*(n+1)/2 non-empty subarrays/substrings.
A substring is a subarray, but for a string, CONTIGUOUS
s=”apple”
substring = appl, ple, pple, a, le
A subsequence is a sequence that can be derived from another sequence, without changing the order of the remaining elements. DOES NOT NEED TO BE CONTIGUOUS, but they must remain in relative order.
For the same example, there are 15 sub-sequences. They are (1), (2), (3), (4), (1,2), (1,3),(1,4), (2,3), (2,4), (3,4), (1,2,3), (1,2,4), (1,3,4), (2,3,4), (1,2,3,4)
a subset is any combination of elements in the array as long as they exist in any order. [3,1], [3,1,2] are subsets of the base array
Does this successfully loop through the list without throwing out of index errors?
l=0
li=[1,2,3]
while l
yes, if l=0 and you do while l
iterate backwards through a list
for i in range(len(list)-1, -1, -1)
if the list is [1,2,3,4] len(list)-1=3, so we start at index 3, which is the end.
we then use the 3rd parameter, step, to increment backwards
we end on -1, which is the last item of the list list[-1]=4, and the last item in range() is exclusive so it works great
return K largest values in an unsorted list
Adding to a heap while keeping it as a valid heap is log(k), where k is the elements in the heap, which height evaluates to log(k). given an array of N elements, we have to continually add N elements to the array and then heapify them. Since we keep the array at size K, it takes N * log(k) time to create a fixed size heap and find the largest values in it
def kthLargest(nums, k):
returns a descending array with the kth largest elements, we want the last one.
time is above, space is O(k) since we only keep K elements in the array
~~~~Need to talk about quick select too
heap as an array
0 index is root
left = 2n+1
right = 2n+2 where n is the index of the array
[0,3,6,5,9,7,8]
what is a binary tree, binary search tree, n-ary tree
binary tree is a tree where all nodes have at most 2 children
binary search tree is a tree in which all nodes have at most 2 children, all nodes on the left are less than the root, and all nodes on the right are greater than the root. equal values you can add a count variable to the node or do less than or equal to for left side
n-ary tree is a tree with each node can have n children. nothing is mentioned about order
preorder traversal of n-ary tree
Time and space is O(N) bc of the stack or recursion stack
class Solution:
public static List preorderIterative(TreeNode node){
List nodes = new ArrayList<>();
Stack stack = new Stack<>();
stack.push(node);
while (!stack.isEmpty()){
TreeNode n = stack.pop();
nodes.add(n);
for (int i=n.children.size()-1;i>-1;i--){
stack.push(n.children.get(i));
}
}
return nodes;
} public static List preorder(TreeNode node){
List nodes = new ArrayList<>();
preorderHelper(node, nodes);
return nodes;
} private static void preorderHelper(TreeNode node, List nodes){
TreeNode c = node;
// System.out.println(c.value);
nodes.add(c);
for (TreeNode tn : c.children){
preorderHelper(tn, nodes);
}
}postorder traversal of an n-ary tree
class Solution: