Given an array, A
, and index, n
, rotate A
by n
.
For example, n = 3
, [1,2,3,4,5,6,7]
is rotated to [5,6,7,1,2,3,4]
.
- Reverse left partition (
L.length = A.length - n
)[4,3,2,1,5,6,7]
- Reverse right partition (
R.length = n
)[4,3,2,1,7,6,5]
- Reverse whole array
[5,6,7,1,2,3,4]
Time:
Space:
Given an unsorted array A, find the
Max Heap: heapify to max heap, then poll heap
Quick-select
Time:
Space:
eg. given [5,3,1,7,6,4,2]
, output [5,3,2,1,4,6,7]
- Starting from right, find first number smaller than right neighbour (
1
in this case) - Find smallest number bigger, and to the right, of the number found in step 1 (
2
in this case) - Swap the numbers found in step 1 and 2 (
[5,3,2,7,6,4,1]
) - Reverse array for index more than the number found in step 1 (
[5,3,2,1,4,6,7]
)
Time:
Space:
Given only a stack or only a queue, reverse them without the use of any additional auxiliary data structure.
Hint: make use of the call stack to store data
void reverse(A) {
if (A.isEmpty()) {
return; // stop when A is empty
}
int current = A.poll();
reverse(A); // recursively call reverse and add to call stack
A.add(current);
}
Time:
Space:
Node reversed_list = null
Node current = head
while current is not null
Node next = current.next
current.next = reversed_list
reversed_list = current
current = next
head = reversed_list
Time:
Space:
function height(tree)
if tree is null
return 0
heightLeft = height(tree.left)
heightRight = height(tree.left)
return max(heightLeft, heightRight) + 1
Time:
Space:
- Run BFS to find the furthest node,
$A$ , from given source node - While keeping a counter for distance travelled, run BFS from
$A$ to find furthest node,$B$ , from$A$ - Diameter is distance from
$A$ to$B$
BFS:
Assuming Binary Tree, where
Time:
Space:
Intuition, given 2 nodes,
- If current node is
$x$ or$y$ , then LCA is current node - If
$x$ is found on left subtree and$y$ is found on right subtree, then LCA is current node - If a node
$x$ is found, and$y$ isn't, it means$y$ is child of$x$ and$y$ is LCA - Else, recursively call this algorithm on left and right subtrees
# This assumes x and y can be found in the tree
function findLCA(root, x, y)
if root is null
return null
# Case 1: current node is x or y
if root == x or root == y
return root
# Look for keys in left and right subtrees
leftLCA = findLCA(root.left, x, y)
rightLCA = findLCA(root.right, x, y)
# Case 2: nodes found on either side of tree:
if leftLCA != null and rightLCA != null
return root
# Case 3: one node is child of the other:
if leftLCA != null
return leftLCA
else
return rightLCA
Time:
Space:
- In-order traversal
- Perform right rotation on node if there exists left child on node
Time:
Space:
Given two arrays of sorted integers A and B of size N and M respectively, give an efficient algorithm to find the combined median of all the values in A and B.
- Mergesort:
$O(n\log n)$ - Merge:
$O(n)$
[ {COUNT1}, TL, TR, {COUNT2} ]
[ {COUNT1}, BL, BR, {COUNT2} ]
Invariants:
- COUNT1 == COUNT2
- TL < BR
- BL < TR
Time:
Given
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> pq = new PriorityQueue<>((x, y) -> x.val - y.val);
// insert first element of each list to min heap
for (int i = 0; i < lists.length; i++) {
pq.add(lists[i]);
}
// create new empty linkedlist (note: nodes are moved here, not created)
ListNode head = new ListNode(0);
ListNode toReturn = head;
while (pq.size() > 0) {
// poll smallest element from min heap
ListNode current = pq.poll();
// add next element of smallest element if exist
if (current.next != null) {
pq.add(current.next);
}
// shift head pointer
head.next = current;
head = current;
}
return toReturn.next;
}
- Max heap size =
$O(k)$ at any point of time - Each Insert/ExtractMin operation is
$O(\log k)$ - This is done
$n$ times
Time:
Space:
Suppose you are given two sets of 2-dimensional points
Similar to counting total number of inversions in an array.
Time:
Check if a given graph,
- Start from any node, colour it red
- While there are still uncoloured nodes,
- Colour all neighbours of red nodes blue
- Colour all neighbours of blue nodes red
- If there are any 2 adjacent nodes with the same colour, bipartite graph does not exist
- Else, the 2 coloured sets represent the 2 required set of nodes
- Use Topological Sort to get topological ordering of nodes
- Init all dist estimate as
$-\infty$ - For every vertex
$u$ in topological order,- For every adjacent vertex
$v$ of$u$ ,- If
$dist[v] < dist[u] + weight(u, v)$ ,$dist[v] = dist[u] + weight(u, v)$
- If
- For every adjacent vertex
Time:
Note: relax condition is swapped to
$<$ instead of$>$
- Use deque (doubly-ended queue) instead of queue
- Push
$0$ -weight edge to front,$K$ -weight edge to back of deque - Do BFS, but pop from front of deque (ie. keep visiting 0 first)
Time:
Only works if one of the edge is
$0$ weight
Given an array,
public boolean bfs(int[] arr, int target) {
Arrays.sort(arr);
LinkedList<Node> queue = new LinkedList<>();
queue.add(new Node(0, -1));
while (!queue.isEmpty()) {
int numLoops = queue.size();
for (int i = 0; i < numLoops; i++) {
Node curr = queue.poll();
for (int j = curr.arrIdx + 1; j < arr.length; j++) {
int sum = arr[j] + curr.sum;
if (sum == target) {
return true;
} else if (sum < target) {
queue.add(new Node(sum, j));
}
}
}
}
return false;
}
Brute force BFS approach
In worst case, all possible subsets (all nodes in the tree) have to be visited
Number of nodes
Time: