Leetcode Flashcards
Two Sum
Given an array of integers nums
and an integer target
, return indices of the two numbers such that they add up to target.
- Use
Map
to save already seen elements - Iterate through
nums
- If
target - nums[i]
exists inMap
–> return
O(n) time
O(n) space
Valid Parentheses
Given a string s
containing just the characters (
, )
, {
, }
, [
and ]
, determine if the input string is valid.
- Use
Stack
to push opened brackets - For closed –
pop()
(checkisEmpty()
first!) - Check if pair is valid
- If
Stack
is not empty – returnfalse
elsetrue
O(n) time
O(n) space
Merge Two Sorted Lists
You are given the heads of two sorted linked lists list1
and list2
. Merge the two lists in a one sorted list.
- Create an empty
Node
ashead
while (list1 != null && list2 != null)
while (list1 != null)
while (list2 != null)
- Return
head.next
O(m + n) time
O(m + n) space
Best Time to Buy and Sell Stock
You are given an array prices
where prices[i]
is the price of a given stock on the ith
day.
You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.
Return the maximum profit you can achieve from this transaction.
- Keep track of a min seen value
- Compute profit for each
price
:price[i] - min
- Update
maxProfit
O(n) time
O(1) space
Valid Palindrome
Given a string s
, return true
if it is a palindrome, or false
otherwise.
while (left < right)
- If
!=
->false
- Return
true
O(n) time
O(1) space
Invert Binary Tree
Given the root
of a binary tree, invert the tree, and return its root.
- Recursive
swap(Node root)
- If
root == null
return - Swap
left
andright
swap(root.left)
swap(root.right)
O(n) time
O(n) space
Valid Anagram
Given two strings s
and t
, return true
if t
is an anagram of s
, and false
otherwise.
An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
- Create a char
Map
for each word - If maps are equal ->
true
O(m + n) time
O(m + n) space
Binary Search
Given an array of integers nums
which is sorted in ascending order, and an integer target
, write a function to search target
in nums
. If target exists, then return its index. Otherwise, return -1
.
-
while (left <= right)
2 .mid = (left + right) / 2
- Greater ->
left = mid + 1
- Less ->
right = mid - 1
- Equal -> return
mid
O(log n) time
O(1) space
Flood Fill
An image is represented by an m x n
integer grid image
where image[i][j]
represents the pixel value of the image.
You are also given three integers sr
, sc
, and color
. You should perform a flood fill on the image starting from the pixel image[sr][sc]
.
To perform a flood fill, consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color), and so on. Replace the color of all of the aforementioned pixels with color.
- Recursive
recolor(int[][] image, int x, int y, int oldColor, int newColor)
- If out of bounds or already recolored -> return
- Change color
- Call
recolor()
four times for all directions
O(n) time
O(n) space
Lowest Common Ancestor of a Binary Search Tree
Given a binary search tree (BST), find the lowest common ancestor (LCA) node of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p
and q
as the lowest node in T
that has both p
and q
as descendants (where we allow a node to be a descendant of itself).”
- Recursive
find(Node root, Node p, Node q)
- If
p
andq
are of different sides -> returnroot
- If
p == root
orq == root
-> returnroot
- If both on the left – search left subtree
- If both on the right – search right subtree
O(log n) time
O(lon n) space
Balanced Binary Tree
Given a binary tree, determine if it is
height-balanced.
A height-balanced binary tree is a binary tree in which the depth of the two subtrees of every node never differs by more than one.
- Recursive
height(TreeNode root, int height)
- If
Math.abs(left - right) > 1
-> return-1
- Return
Math.max(left, right)
O(n) time
O(n) space
Linked List Cycle
Given head
, the head of a linked list, determine if the linked list has a cycle in it.
- Use fast and slow pointers
while (fast != null && fast.next != null)
- If
fast == slow
-> returntrue
O(n) time
O(1) space
Implement Queue using Stacks
Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal queue (push
, peek
, pop
, and empty
).
-
push()
to firstStack
- On
pop()
andpeek()
return from secondStack
- If second
Stack
is empty – transfer elements from first to second
O(n) time for push and pop
O(n) space
First Bad Version
Suppose you have n
versions [1, 2, ..., n]
and you want to find out the first bad one, which causes all the following ones to be bad.
You are given an API bool isBadVersion(version)
which returns whether version
is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.
- Binary search
-
int mid = left + (right - left) / 2
(not to overflowint
!) - If
mid
is bad – search on the left - Return
left
O(log n) time
O(1) space
Ransom Note
Given two strings ransomNote
and magazine
, return true
if ransomNote
can be constructed by using the letters from magazine
and false
otherwise.
- Create char
Map
of amagazine
- Iterate through
ransomNote
- If
ransomNote[i]
does not exist inMap
->false
- Lower the counter in
Map
as the char was used - Return
true
O(m + n) time
O(1) space
Climbing Stairs
You are climbing a staircase. It takes n
steps to reach the top.
Each time you can either climb 1
or 2
steps. In how many distinct ways can you climb to the top?
- Go from top to bottom
- Recursive
count(int n)
with memoization memo.put(1, 1); memo.put(2, 2)
count = count(n - 1) + count(n - 2)
- If is in
memo
-> return - Else put in
memo
-> returncount
O(n) time
O(n) space
Longest Palindrome
Given a string s
which consists of lowercase or uppercase letters, return the length of the longest palindrome that can be built with those letters.
- Create a char
Map
- If
count % 2 == 0
->maxLength += 2
- If
maxLength < s.length()
->maxLength += 1
(for cases likeaca
,abeba
, etc.
O(n) time
O(1) space
Reverse Linked List
Given the head
of a singly linked list, reverse the list, and return the reversed list.
Node prev = null
while (head != null) {
Node next = head.next
head.next = prev
prev = head
head = next
}
O(n) time
O(1) space
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.
Sort and return mid
OR
- Take first element as a
candidate
- Iterate through
nums
- If
count == 0
->candidate = nums[i]
- If
nums[i] == candidate
->count++
- Else
count--
- Return
candidate
O(n) time
O(1) space
Add Binary
Given two binary strings a
and b
, return their sum as a binary string.
- Two pointers from the end of each string
- Init
carry = 0
- Iterate backwards while both pointers
>= 0
result.append(sum % 2)
carry = sum / 2
- Return
result.reverse().toString()
O(n) time
O(1) space
Diameter of Binary Tree
Given the root
of a binary tree, return the length of the diameter of the tree.
The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root
.
The length of a path between two nodes is represented by the number of edges between them.
- Recursive
heightAndDiameter(Node root)
- If
root == null
->Pair(0, 0)
- Call for
left
andright
maxHeight = max(left.height, right.height) + 1
maxDiameter = max(left.height + right.height, max(left.diameter, right.diameter)
- Return
Pair(maxHeight, maxDiameter)
O(n) time
O(n) space
Middle of the Linked List
Given the head
of a singly linked list, return the middle node of the linked list.
If there are two middle nodes, return the second middle node.
- Fast and slow pointers
- Return slow
O(n) time
O(1) space
Maximum Depth of Binary Tree
Given the root
of a binary tree, return its maximum depth.
A binary tree’s maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
- Recursive
depth(Node root)
- If
root == null
->0
- Return
max(left, right) + 1
O(n) time
O(n) space
Contains Duplicate
Given an integer array nums
, return true
if any value appears at least twice in the array, and return false
if every element is distinct.
- Use
Set
of already seen elements - If
seen.contains(nums[i])
->false
- Return
true
O(n) time
O(n) space
Maximum Subarray
Given an integer array nums
, find the subarray with the largest sum, and return its sum.
- Iterate
nums
:sum += nums[i]
- If
sum < nums[i]
->sum = nums[i]
max = max(max, sum)
- Return
max
O(n) time
O(1) space
Insert Interval
You are given an array of non-overlapping intervals intervals
where intervals[i] = [starti, endi]
represent the start and the end of the ith
interval and intervals
is sorted in ascending order by starti
. You are also given an interval newInterval = [start, end]
that represents the start and end of another interval.
Insert newInterval
into intervals
such that intervals
is still sorted in ascending order by starti
and intervals
still does not have any overlapping intervals (merge overlapping intervals if necessary).
- Use 3
while
-loops with single pointeri
- Left elements:
newInterval[0] > intervals[i][1]
- Merge:
newInterval[1] >= intervals[i][0]
newInterval[0] = min(newInterval[0], interval[0]
newInterval[1] = max(newInterval[1], interval[1]
- Rest elements:
i < intervals.length
O(n) time
O(n) space
Longest Substring Without Repeating Characters
Given a string s
, find the length of the longest substring without repeating characters.
- Use char
Map
and two pointers - If
Map
contains char -> movemax(get() + 1, left)
length = right - left + 1
- Update
max = max(length, max)
- Move
right += 1
O(n) time
O(1) space
Evaluate Reverse Polish Notation
You are given an array of strings tokens
that represents an arithmetic expression in a Reverse Polish Notation.
Evaluate the expression. Return an integer that represents the value of the expression.
- Use
Stack
topush()
numbers and ops results -
pop()
on ops eval(int b, int a, String op)
- Return
pop()
O(n) time
O(n) space
Three Sum
Given an integer array nums
, return all the triplets [nums[i], nums[j], nums[k]]
such that i != j, i != k, and j != k
, and nums[i] + nums[j] + nums[k] == 0
.
Notice that the solution set must not contain duplicate triplets.
- Use
Set
to avoid duplicates - Sort
nums
- Iterate
i = [0, N - 2]
- Two pointers
left = i + 1; right = N - 1
- If
sum == 0
-> add - If
sum > 0
-> moveright--
- If
sum < 0
-> moveleft++
O(n^2) time
O(n) space
Binary Tree Level Order Traversal
Given the root
of a binary tree, return the level order traversal of its nodes’ values. (i.e., from left to right, level by level).
- Recursive
traverse(Node root, int level, List<List<Integer>> result)
- If
root == null
-> return - If
(level >= result.size()
->add(new ArrayList<>())
result.get(level).add(root.val)
traverse(root.left, level + 1, result)
traverse(root.right, level + 1, result)
O(n) time
O(n) space
01 Matrix
Given an m x n
binary matrix mat
, return the distance of the nearest 0
for each cell.
The distance between two adjacent cells is 1
.
- Use modified BFS
- Use
int[][]
array for possible movement directions - Keep track of
visited[][]
vertices - Add all
0
cells toQueue
and mark them as visited - While
Queue
is not empty, move to all possible directions that are not visited - Mark them as visited and update the distance
O(m * n) time
O(m * n) space
K Closest Point to Origin
Given an array of points
where points[i] = [xi, yi]
represents a point on the X-Y
plane and an integer k
, return the k
closest points to the origin (0, 0)
.
Sort by distance and return first k
OR
- Use
PriorityQueue
as max heap - Add each point to
PriorityQueue
- If
size > k
->poll()
- Return all
PriorityQueue
elements
O(nlog k) time
O(k) space
Clone graph
Given a reference of a node
in a connected undirected graph.
Return a deep copy (clone) of the graph.
- Use modified DFS
- Save cloned nodes to a
Map
- Create clone of a current
Node
- Create clones while iterating neighbors
O(n) time
O(n) space
Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
You must implement a solution with O(1)
time complexity for each function.
- Use two stacks – for values and for mins
- Init
min
withInteger.MAX_VALUE
- On
push()
update min-stack if needed - If
pop() == min
-> pop() min-stack and updatemin
O(1) time
O(n) space
Course Schedule
There are a total of numCourses
courses you have to take, labeled from 0
to numCourses - 1
. You are given an array prerequisites
where prerequisites[i] = [ai, bi]
indicates that you must take course bi
first if you want to take course ai
.
Return true
if you can finish all courses. Otherwise, return false
.
- Find cycles using DFS for each
course
- If neighbor vertex was already
visited == 1
-> has cycle - If has cycle -> return
false
- Return
true
O(n) time
O(n) space
Rotting Oranges
You are given an m x n
grid
where each cell can have one of three values:
0
- representing an empty cell,1
- representing a fresh orange, or2
- representing a rotten orange.
Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.
Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1
.
- Use modified BFS
- Count fresh oranges and add all rotten to a
Queue
- Traverse
Queue
level by level, while it is not empty andfresh > 0
- Return
time
iffresh == 0
and-1
otherwise
O(m * n) time
O(m * n) space
Number of Islands
Given an m x n
2D binary grid grid
which represents a map of '1'
s (land) and '0'
s (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
- Use DFS for each
1
to color the islands - Return the number of used colors
O(m * n) time
O(m * n) space
Validate Binary Search Tree
Given the root
of a binary tree, determine if it is a valid binary search tree (BST).
- Recursive
isBST(root, min, max)
- If
root == null
-> true - If
root.val >= max
-> false - If
root.val <= min
-> false - Return
isBST(root.left, min, root) && isBST(root.right, root, max)
O(n) time
O(n) space
Product of Array Except Self
Given an integer array nums
, return an array answer such that answer[i]
is equal to the product of all the elements of nums except nums[i]
.
You must write an algorithm that runs in O(n)
time and without using the division operation.
- Fill
result
with products of left elements ofi
:result[i] = left; left *= nums[i]
- Fill
result
with products of right elements ofi
, multiplied on products of left elements:result[i] *= right; right *= nums[i];
O(n) time
O(1) space
Coin Change
You are given an integer array coins
representing coins of different denominations and an integer amount representing a total amount
of money.
Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1
.
You may assume that you have an infinite number of each kind of coin.
- Use bottom-up DP
- Iterate from
0
toamount
- On each step find
min
of all possible previous steps:Math.min(memo.get(currentAmount - coin) + 1, count)
- Return
memo.getOrDefault(amount, -1)
O(n * m) time
O(m) space
Longest Common Subsequence
Given two strings text1
and text2
, return the length of their longest common subsequence. If there is no common subsequence, return 0
.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
- Use 2D-DP
- If
charAt(i) == charAt(j)
->memo[i][j] = memo[i - 1][j - 1] + 1
- Else ->
memo[i][j] = max(memo[i - 1][j], memo[i][j - 1])
- Return
memo[N - 1, M - 1]
O(n * m) time
O(n * m) space
Coin Change II
You are given an integer array coins
representing coins of different denominations and an integer amount
representing a total amount of money.
Return the number of combinations that make up that amount. If that amount of money cannot be made up by any combination of the coins, return 0
.
- Use bottom-up DP,
memo[0] = 1
- Iterate
coins
- Iterate
amount
-> memo[i] += memo[i - coin]` - Return
memo[amount]
O(n * m) time
O(m) space
Merge Intervals
Given an array of intervals
where intervals[i] = [starti, endi]
, merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
- Sort
intervals
bystarti
start = intervals[0][0]; end = intervals[0][1]
- if
end < current[0]
-> addnew int[] {start, end}
- else
end = max(end, current[1])
- add
new int[] {start, end}
O(nlog n) time
O(n) space
Search in Rotated Sorted Array
There is an integer array nums
sorted in ascending order (with distinct values).
Prior to being passed to your function, nums
is possibly rotated at an unknown pivot index k
. For example, [0,1,2,4,5,6,7]
might be rotated at pivot index 3
and become [4,5,6,7,0,1,2]
.
Given the array nums
after the possible rotation and an integer target
, return the index of target
if it is in nums
, or -1
if it is not in nums
.
- Find
pivot
using BS - if
nums[mid] > nums[right]
->left = mid + 1
- Else
right = mid
- Find
target
in[0; pivot)
or[pivot, N]
O(log n) time
O(1) space
Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p
and q
as the lowest node in T
that has both p
and q
as descendants (where we allow a node to be a descendant of itself).”
- Recursive
lca(root, q, p)
- If
root == null || root == q || root == p
->root
- Go left and right
- If both
left
andright
exist ->root
- Else -> either
left
ofright
O(n) time
O(n) space
Permutations
Given an array nums
of distinct integers, return all the possible permutations. You can return the answer in any order
- Recursive backtrack
b(nums, permutation, result)
- If
permutation.size() == nums.length
->result.add()
- iterate
nums
- If
!permutation.contains(num)
->b()
O(n * n!) time
O(n) space
Combination Sum
Given an array of distinct integers candidates
and a target integer target
, return a list of all unique combinations of candidates where the chosen numbers sum to target
. You may return the combinations in any order.
The same number may be chosen from candidates
an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
- Recursive backtrack
b(nums, permutation, remains, start, result)
- if
remains == 0
->result.add()
- If
remains < 0
-> return - Iterate
nums
fromstart
b(nums, newPermutation, remains - nums[i], i, result)
O(2^n) time
O(2^n) space
Accounts Merge
Given a list of accounts
where each element accounts[i]
is a list of strings, where the first element accounts[i][0]
is a name, and the rest of the elements are emails representing emails of the account.
Now, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some common email to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name.
After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order.
- Create
adjList
- Create
namesMap
for each email - Perform DFS to mark graph components
- Each component is a separate account
O(nlog n) time
O(n) space
Time Based Key-Value Store
Design a time-based key-value data structure that can store multiple values for the same key at different time stamps and retrieve the key’s value at a certain timestamp.
Implement the TimeMap
class:
String get(String key, int timestamp)
Returns a value such that set
was called previously, with timestamp_prev <= timestamp
. If there are multiple such values, it returns the value associated with the largest timestamp_prev
. If there are no values, it returns ""
.
- Create class
Node(String value, int timestamp)
- Create inner
Map<String, List<Node>>
- Use BS to find
Node
inList
O(log n) time
O(n) space
In-place Quick Sort
Given an array nums
sort it in-place.
- Use recursive
quickSort(int[] nums, int left, int right)
- If
left >= right
-> return l = left; r = right; pivot = (l + r) / 2
- If
nums[l] < pivot
->l++
- If
nums[r] > pivot
->r--
- Else
swap()
,l++
,r--
quickSort(left, r)
quickSort(l, right)
O(n logn) time
O(log n) space
Sort Colors
Given an array nums
with n
objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.
We will use the integers 0
, 1
, and 2
to represent the color red, white, and blue, respectively.
Use Counting Sort
OR
- Use Dutch Flag Algo
red = 0; white = 0; blue = N -1
while (white <= blue)
- If
nums[white] == WHITE
->white++
- If
nums[white] == RED
->swap(); white++; red++
- If
nums[white] == BLUE
->swap(); blue--
O(n) time
O(1) space
Word Search
Given an m x n
grid of characters board
and a string word
, return true
if word exists in the grid.
The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.
- Use modified DFS for each
board[i][j] = charAt(0)
- If
pointer == word.length()
-> returntrue
- If
charAt(pointer) != board[x][y]
-> continue - Else add neighbors and
pointer++
- If
visited[x][y] == 1
->visited[x][y] = 0; pointer--
- Return
false
O(3^word.length()) time
O(m * n) space
Roman to Integer
Given a roman numeral, convert it to an integer.
- Create
Map
of roman to integer conversions - Iterate
roman
- If
prev < current
->result -= prev
- Else ->
result +=prev
- Update
prev = current
- Return
result + prev
O(n) time
O(1) space
Backspace String Compare
Given two strings s
and t
, return true
if they are equal when both are typed into empty text editors. '#'
means a backspace character.
Note that after backspacing an empty text, the text will continue empty.
Use stack for each string and compare stacks
OR
- Run two pointers from the end of the strings
while (i >= 0 || j >= 0)
- Use
i = skip(String s, int i)
to skip characters - If
charAt(i) != charAt(j)
-> returnfalse
- If
(i >= 0 && j < 0) || (j >= 0 && i < 0)
-> returnfalse
- Return
true
O(n + m) time
O(1) space
Same Tree
Given the roots of two binary trees p
and q
, write a function to check if they are the same or not.
- Use recursive
isSame(p, q)
- If both
null
-> returntrue
- If one
null
-> returnfalse
- If not equal -> return
false
- Return
isSame(p.left, q.left) && isSame(p.right, q.right)
O(n) time
O(n) space
Palindrom Linked List
Given the head
of a singly linked list, return true
if it is a palindrome or false
otherwise.
Find mid, while pushing slow
to Stack
. Compare second half with Stack
OR
- Find
mid
- Reverse from
mid
, newsecondHalfHead = prev
- Compare
while (secondHalfHead != null)
O(n) time
O(1) space
Move Zeroes
Given an integer array nums
, move all 0
’s to the end of it while maintaining the relative order of the non-zero elements.
- Use two pointers
zero = 0; nonZero = 0
- Move them in a Dutch Flag fashion and
swap()
O(n) time
O(1) space
Subtree of Another Tree
Given the roots of two binary trees root
and subRoot
, return true
if there is a subtree of root
with the same structure and node values of subRoot
and false
otherwise.
- Use two recursive functions:
isSubtree(root, subRoot)
andisEqual
- If
root == null
-> return false - If
isEqual(root, subRoot)
-> return true - Return
isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot)
O(m * n) time
O(h2) space
Counting Bits
Given an integer n
, return an array ans
of length n + 1
such that for each i
(0 <= i <= n
), ans[i]
is the number of 1
’s in the binary representation of i
.
- Use DP
dp[i] = dp[i / 2] + (i % 2)
- For even numbers number of
1
in N and N/2 is the same - For odd numbers add one more
1
O(n) time
O(n) space
Symmetric Tree
Given the root
of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).
- Use recursive
isMirror(left, right)
- Return
isMirror(left.left, right.right) && isMirror(left.right, right.left)
O(n) time
O(log n) space
Squares of a Sorted Array
Given an integer array nums
sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order.
- Use two pointers
left = 0; right = N -1
- Fill new array
squares
from the end
O(n) time
O(n) space
Convert Sorted Array to Binary Search Tree
Given an integer array nums
where the elements are sorted in ascending order, convert it to a height-balanced binary search tree.
- Use recursive
toBST(nums, left, right)
- If
left > right
->return
root = nums[mid]
root.left = toBST(nums, left, mid - 1)
root.right = toBST(nums, mid + 1, right)
O(n) time
O(log n) space
Longest Common Prefix
Write a function to find the longest common prefix string amongst an array
of strings.
If there is no common prefix, return an empty string ""
.
Sort array
and compare first and last string
OR
1. Get first
string
2. Compare i
‘th letter for all the strings
3. If !=
-> return prefix
4. Return prefix
O(m * n) time
O(m) space
Generate Parentheses
Given n
pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
- Use recursive
backtrack(String prefix, int opened, int closed, int max, List<String> result)
- If
prefix.length() == max * 2
->add()
and return - If
opened < max
->backtrack(prefix + "(", opened + 1, ...)
- If
opened > closed
->backtrack(prefix + ")", opened, closed + 1, ...)
O(2^2n) time
O(n) space
Binary Tree Right Side View
Given the root
of a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.
- Use level-by-level BST
- On each level take last
Queue
element
O(n) time
O(n) space
Reverse String
Write a function that reverses a string. The input string is given as an array of characters s
.
You must do this by modifying the input array in-place with O(1) extra memory.
- Use two pointers
-
while (left < right)
->swap()
O(n) time
O(1) space
One Edit Distance
Given two strings first
and second
, determine if they are both one edit distance apart.
- Let
first
to be the shortest - If
second.length - first.length > 1
-> returnfalse
- Use two pointers
- If
f.charAt(i) == s.charAt(j)
-> move pointers - Else -> if
hasEdit
-> returnfalse
elsehasEdit = true
- If
f.length() == s.length()
-> move pointers - Else move only
j
- Return
true
O(n) time
O(1) space
Letter Combinations of a Phone Number
Given a string containing digits from 2-9
inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.
- Use recursive
backtrack(String digits, String prefix, int current, List<String> result)
- If
prefix.length() == digits.length() ->
add()` and return - Run
backtrack(digits, prefix + letter, current + 1, result)
for each letter on a current button
O(4^n) time
O(4^n) space
Subsets
Given an integer array nums
of unique elements, return all possible subsets (the power set).
The solution set must not contain duplicate subsets.
- Use recursive
backtrack(int[] nums, int start, List<Integer> subset, List<List<Integer>> result)
add()
- For each
nums[i]
starting fromstart
->backtrack(i + 1)
O(2^n) time
O(2^n) space
Spiral Matrix
Given an m x n
matrix, return all elements of the matrix
in spiral order.
while (rowStart <= rowEnd && colStart <= colEnd)
switch (direction)
direction = (direction + 1) % 4
O(m * n) time
O(m * n) space
Valid Sudoku
Determine if a 9 x 9
Sudoku board
is valid.
- Use
Set
to store seen positions - If
board[i][j] == '.'
-> skip - If
!seen.add(cell + " in row " + i)
-> returnfalse
- If
!seen.add(cell + " in col " + j)
-> returnfalse
- If
!seen.add(cell + " in square " + i/3 + ":" + j/3)
-> returnfalse
- Return
true
O(m * n) time
O(m * n) space
Add Two Numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
- Create empty
head
andcurrent = head
while (first != null || second != null)
sum += carry + first.val + second.val
current.next = Node(sum % 10)
carry = sum / 10
- If
carry != 0
->current.next = Node(1)
- Return
head
O(n) time
O(n) space
Remove Nth Node From End of List
Given the head
of a linked list, remove the nth
node from the end of the list and return its head.
- Use
fast
andslow
pointers - Move
fast
n
times - If
fast == null
-> returnhead.next
(head deletion) -
while (fast.next != null)
-> move both pointers slow.next = slow.next.next
- Return
head
O(n) time
O(1) space
Implement Trie
void insert(String word)
boolean search(String word)
boolean startsWith(String prefix)
- Create internal
Node(Map<Character, Integer> children, boolean isTerminal)
- Insert each
word
character as aNode
- While searching if
next == null
-> returnfalse
- Else return
current.isTerminal
forsearch()
or justtrue
forstartsWith()
O(n) time
O(n) space
Design Add and Search Words Data Structure
Design a data structure that supports adding new words and finding if a string matches any previously added string.
Implement the WordDictionary
class:
void addWord(word)
-
boolean search(word)
–word
may contain dots'.'
where dots can be matched with any letter
- Use recursive
search(String word, int start, Node current)
- If
start == word.length()
-> returncurrent.isTerminal
- If
word[c] == '.'
-> for eachcurrent.childen
runsearch(i + 1)
O(n) time for add() and O(alphabet^n) for search()
O(n) space
Group Anagrams
Given an array of strings strs
, group the anagrams together. You can return the answer in any order.
- Either
sortHash()
orcountHash()
eachstr
- For
countHash()
useint[26]
andint[c - 'a]++
- Use hashes as keys for a
Map
- Return
new ArrayList<>(map.values())
O(n * klog k) time
O(n) space
Longest Palindromic Substring
Given a string s
, return the longest palindromic substring in s
.
- Use 2D-DP with
left = [N-1; 0]
andright = [left; N - 1]
- If
charAt(left) != charAt(right)
->continue
currentLength = right - left + 1
- If
currentLength <= 2
(“a”, “aa”) ordp[left + 1][right - 1] == 1
->dp[left][right] = 1
- Update
maxLength
if needed ->from = left; to = right
- Return
substring(from, to + 1)
O(n^2) time
O(n^2) space
Meeting Rooms
Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...]
, determine if a person could attend all meetings.
- Sort
intervals
by meeting start time - Iterate. If
intervals[i].start < intervals[i - 1].end
-> returnfalse
- Return
true
O(nlog n) time
O(1) space
Permutations II
Given a collection of numbers, nums
, that might contain duplicates, return all possible unique permutations in any order.
- Use recursive
backtrack(int[] nums, int[] used, List<Integer> tmp, List<List<Integer>> result)
- If
tmp.size() == nums.length
->add()
and return - If
used[i]
ori > 0 && nums[i] = nums[i - 1] && !used[i - 1]
->continue
tmp.add(nums[i]); used[i] = 1; backtrack(); tmp.remove(N - 1); used[i] = 0
O(n!) time
O(n!) space
Subsets II
Given an integer array nums
that may contain duplicates, return all possible subsets (the power set).
- Use recursive
backtrack(int[] nums, List<Integer> tmp, int start, List<List<Integer>> result)
add()
- If
i > start && nums[i] == nums[i - 1]
->continue
tmp.add(nums[i]); backtrack(i + 1); tmp.remove(N - 1)
O(2^n) time
O(2^n) space
Combination Sum II
Given a collection of candidate numbers (candidates
) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sum to target
.
Each number in candidates
may only be used once in the combination.
- Use recursive
backtrack(int[] candidates, int start, List<Integer> tmp, int remains, List<List<Integer> result)
- If
remains < 0
-> return - If
remains == 0
->add()
and return - if
i > start && candidates[i] == candidates[i - 1]
->continue
tmp.add(nums[i]); backtrack(i + 1); tmp.remove(N - 1)
O(2^n) time
O(2^n) space
Find All Anagrams in a String
Given two strings s
and p
, return an array of all the start indices of p
’s anagrams in s
.
- If
anagram.length() > input.length()
-> return - Use two pointers to mark window
- Move
right
up toanagram.length()
, filling two freq maps - If
equal
->positions.add(0)
- Move
left
andright
up toinput.length()
-
windowMap[leftChar -'a
]–` windowMap[rightChar - 'a[]++
- If
equal
->positions.add(left)
- Return
positions
O(n) time
O(1) space
Maximum Width of Binary Tree
Given the root
of a binary tree, return the maximum width of the given tree.
The maximum width of a tree is the maximum width among all levels.
The width of one level is defined as the length between the end-nodes (the leftmost and rightmost non-null nodes), where the null nodes between the end-nodes that would be present in a complete binary tree extending down to that level are also counted into the length calculation.
- Use level-by-level BFS
- Save
Pair(index, node)
inDeque
leftIndex = 2 * parent.index
rightIndex = 2 * parent.index + 1
- On each level compute
width = deque.peekLast().index - deque.peekFirst().index + 1
- Update
maxWidth
if needed
O(n) time
O(n) space
Word Break
Given a string s
and a dictionary of strings wordDict
, return true
if s
can be segmented into a space-separated sequence of one or more dictionary words.
Note that the same word in the dictionary may be reused multiple times in the segmentation.
- Use recursive
backtrack(String s, List<String> wordDict, Set<String> failedChecks)
- If
s.isEmpty() -> return
true` - If
failedChecks.contains(s)
-> returnfalse
- For each
word
->canBeSegmented = s.startsWith(word) && backtrack(s.substring(word.length), wordDict, failedChecks)
- Return
false
O(n^3) time
O(n) space
Last Stone Weight
You are given an array of integers stones
where stones[i]
is the weight of the ith
stone.
We are playing a game with the stones. On each turn, we choose the heaviest two stones and smash them together. Suppose the heaviest two stones have weights x
and y
with x <= y
. The result of this smash is:
- If
x == y
, both stones are destroyed - If
x != y
, the stone of weightx
is destroyed, and the stone of weighty
has new weighty - x
.
At the end of the game, there is at most one stone left.
Return the weight of the last remaining stone. If there are no stones left, return 0
.
- Use
maxHeap = new PriorityQueue(compare(s2, s1))
- Add all
stones
tomaxHeap
while (maxHead.size() > 1)
- if
first != second
->maxHeap.offer(first - second)
- Return
maxHeap.isEmpty() ? 0 : maxHeap.poll()
O(n logn) time
O(n) space
Kth Largest Element in a Stream
Design a class to find the kth
largest element in a stream. Note that it is the kth
largest element in the sorted order, not the kth
distinct element.
Implement KthLargest
class:
-
int add(int val)
Appends the integerval
to the stream and returns the element representing thekth
largest element in the stream.
- Use
minHeap = new PriorityQueue(compare(n1, n2))
minHeap.offer(val)
- If
minHeap.size() > k
->minHeap.poll()
- Return
minHeap.peek()
O(n logk) time
O(k) space
Path Sum
Given the root
of a binary tree and an integer targetSum
, return true
if the tree has a root-to-leaf path such that adding up all the values along the path equals targetSum
.
- Use recursive
hasPath(root, remains)
- If
root == null
-> returnfalse
remains -= root.val
- If
root.left == null && root.right == null
-> returnremains == 0
- Return
hasPath(left, remains) || hasPath(right, remains)
O(n) time
O(h) space
Path Sum II
Given the root
of a binary tree and an integer targetSum
, return all root-to-leaf paths where the sum of the node values in the path equals targetSum
.
- Use recursive
backtrack(Node root, List<Integer> currentPath, int remains, List<List<Integer>> result)
- If
root == null
-> returnfalse
currentPath.add(root.val)
- If
root.right == null && root.left == null && remains == root.val
->add()
- Else
backtrack(left, remains - root.val); backtrack(right, remains - root.val)
currentPath.remove(N - 1)
O(n) time
O(n) space
Path Sum III
Given the root
of a binary tree and an integer targetSum
, return the number of paths where the sum of the values along the path equals targetSum
.
The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes).
- Use recursive
pathSum(Node root, long currentSum, int targetSum, Map<Long, Integer> memo)
- If
root == null
-> return0
currentSum += root.val
currentPath = currentSum == targetSum ? 1 : 0
prevPaths = memo.getOrDefault(currentSum - targetSum, 0)
memo.merge(currentSum, 1, Integer::sum)
result = currentPath + prevPaths + pathSum(left) + pathSum(right)
memo.merge(currentSum, -1, Integer::sum)
- Return
result
O(n) time
O(n) space
Subarray Sum Equals K
Given an array of integers nums
and an integer targetSum
, return the total number of subarrays whose sum equals to targetSum
.
- Use
Map
to store prefix sum frequencies - Iterate
nums
currentSubarray = currentSum == targetSum ? 1 : 0
prevSubarrays = map.getOrDefault(currentSum - targetSum, 0)
count += currentSubarray + prevSubarrays
map.merge(currentSum, 1, Integer::sum)
- Return
count
O(n) time
O(n) space
Top K Frequent Elements
Given an integer array nums
and an integer k
, return the k
most frequent elements. You may return the answer in any order.
Use minHeap
OR
- Create a
freqMap
- Put
keys
inList<Integer>[] frequencyBuckets
withi = value
- Iterate
frequencyBuckets
from the end to get the most frequent elements
O(n) time
O(n) space
Top K Frequent Words
Given an array of strings words
and an integer k
, return the k
most frequent strings.
Return the answer sorted by the frequency from highest to lowest. Sort the words with the same frequency by their lexicographical order.
- Use
minHeap
ofmaxHeap
- Create a
freqMap
and put its entries in the heap - If using
minHeap
->result.add(0, poll())
because it should be sorted from highest to lowest frequency
O(n logk) time
O(n + k) space
Longest Consecutive Sequence
Given an unsorted array of integers nums
, return the length of the longest consecutive elements sequence.
You must write an algorithm that runs in O(n)
time.
- Add
nums
to aSet
to getO(1)
element search time - Iterate
numsSet
- If
contains(num - 1)
->continue
while (contains(num + 1)) count++
- Update
max
if needed - Return
max
O(n) time
O(n) space
Daily Temperatures
Given an array of integers temperatures
represents the daily temperatures, return an array answer
such that answer[i]
is the number of days you have to wait after the ith
day to get a warmer temperature. If there is no future day for which this is possible, keep answer[i] == 0
instead.
- Use
Stack
to store previous indicies - Iterate
temperatures
while (!stack.isEmpty() && t[stack.peek()] < t[current]
prev = stack.pop()
result[prev] = current - prev
stack.push(current)
- Return
result
O(n) time
O(n) space
Reorder List
You are given the head
of a singly linked-list. The list can be represented as:L0 → L1 → … → Ln - 1 → Ln
Reorder the list to be on the following form:L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
You may not modify the values in the list’s nodes. Only nodes themselves may be changed.
- Find
mid
and remove it from the first list:prev.next = null
- Reverse second list
- Merge two lists together
O(n) time
O(1) space
Container With Most Water
You are given an integer array height
of length n
. There are n
vertical lines drawn such that the two endpoints of the ith
line are (i, 0)
and (i, height[i])
.
Find two lines that together with the x-axis form a container, such that the container contains the most water.
Return the maximum amount of water a container can store.
- Use two pointers
space = Math.min(height[left], height[right]) * (right - left)
- If
height[left] < height[right]
-> moveleft++
- Else -> move
right--
- Return
maxSpace
O(n) time
O(1) space
Search a 2D Matrix
You are given an m x n
integer matrix matrix
with the following two properties:
- Each row is sorted in non-decreasing order.
- The first integer of each row is greater than the last integer of the previous row.
Given an integer target
, return true
if target
is in matrix
or false
otherwise.
Use binary search twice: to find a row
and to find a target
in a row
O(log n + log m) time
O(1) space
Max Area of Island
You are given an m x n
binary matrix grid
. An island is a group of 1
’s (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.
The area of an island is the number of cells with a value 1
in the island.
Return the maximum area of an island in grid
. If there is no island, return 0
.
Use DFS to find graph components
O(n) time
O(n) space
Task Scheduler
Given a characters array tasks
, representing the tasks a CPU needs to do, where each letter represents a different task. Tasks could be done in any order. Each task is done in one unit of time. For each unit of time, the CPU could complete either one task or just be idle.
However, there is a non-negative integer n
that represents the cooldown period between two same tasks (the same letter in the array), that is that there must be at least n
units of time between any two same tasks.
Return the least number of units of times that the CPU will take to finish all the given tasks.
- Create
frequencyMap
and put all frequencies tomaxHeap
- Create
cooldownsMap
while (!maxHeap.isEmpty() || cooldownsMap.isEmpty)
- If
cooldownsMap.contains(currentTime - n - 1)
->remove()
and put back tomaxHeap
- If
!maxHeap.isEmpty()
->poll()
execLeft = currentTask - 1
- If
execLeft > 0
->cooldownsMap.put(currentTime, currentTask)
currentTIme++
- Return
currentTime
O(nlog n) time
O(n) space
Reorganize String
Given a string s
, rearrange the characters of s
so that any two adjacent characters are not the same.
Return any possible rearrangement of s
or return ""
if not possible.
- Create
frequencyMap
and put all entries tomaxHeap
while (maxHeap.size() > 1)
-
poll()
two characters and append tosb
- If
freq > 1
->offer(freq - 1)
- If
!maxHeap.isEmpty()
-> iffreq > 1
-> return""
- Else -> append to
sb
- Return
sb.toString()
O(n) time
O(1) space
Odd Even Linked List
Given the head
of a singly linked list, group all the nodes with odd indices together followed by the nodes with even indices, and return the reordered list.
The first node is considered odd, and the second node is even, and so on.
Note that the relative order inside both the even and odd groups should remain as it was in the input.
You must solve the problem in O(1)
extra space complexity and O(n)
time complexity.
odd = head; even = head.next; evenHead = even
while (even != null && even.next != null)
odd.next = odd.next.next
even.next = even.next.next
odd = odd.next
even = even.next
- In the end
odd.next = evenHead
- Return
head
O(n) time
O(1) space
Pacific Atlantic Water Flow
There is an m x n
rectangular island that borders both the Pacific Ocean and Atlantic Ocean. The Pacific Ocean touches the island’s left and top edges, and the Atlantic Ocean touches the island’s right and bottom edges.
The island is partitioned into a grid of square cells. You are given an m x n
integer matrix heights where heights[r][c]
represents the height above sea level of the cell at coordinate (r, c)
.
The island receives a lot of rain, and the rain water can flow to neighboring cells directly north, south, east, and west if the neighboring cell’s height is less than or equal to the current cell’s height. Water can flow from any cell adjacent to an ocean into the ocean.
Return a 2D list of grid coordinates result
where result[i] = [ri, ci]
denotes that rain water can flow from cell (ri, ci)
to both the Pacific and Atlantic oceans.
- Run DFS with
pacific[][]
for all cells on top and left borders - Run DFS with
atlantic[][]
for all cells on bottom and right borders - Visit cells with
heights[nextRow][nextCol] >= heights[curCol][curRow]
- If cell marked as visited in both
pacific
andatlantic
->add()
- Return
result
O(m * n) time
O(m * n) space
Find Minimum in Rotated Sorted Array
Suppose an array of length n
sorted in ascending order is rotated between 1
and n
times.
Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]]
1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
.
Given the sorted rotated array nums
of unique elements, return the minimum element of this array.
- Use modified BS
- If
nums[mid] > nums[right]
->left = mid + 1
- Else ->
right = mid
- Return
nums[left]
O(log n) time
O(1) space
Rotate Image
You are given an n x n
2D matrix
representing an image, rotate the image by 90 degrees (clockwise).
You have to rotate the image in-place.
- Transpose
matrix
:for [0; N)
-for [0; i)
- Flip columns:
for [0; N)
-for [0; M / 2)
O(n * m) time
O(1) space
Longest Repeating Character Replacement
You are given a string s
and an integer k
. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k
times.
Return the length of the longest substring containing the same letter you can get after performing the above operations.
- Use two pointers
left = 0; right = 0
- Add
s[right]
tofrequencyMap
- Update
mostFrequentCharFrequency
- If
right - left + 1 - mostFrequentCharFrequency > k
-> decrements[left]
frequency and moveleft++
- Update
maxLength
- Move
right
O(n) time
O(1) space
Permutation in String
Given two strings s1
and s2
, return true if s2
contains a permutation of s1
, or false
otherwise.
In other words, return true
if one of s1
’s permutations is the substring of s2
.
- Build two
frequencyMap
s, while forming a window of sizes1.length()
- If
Arrays.equals()
-> returntrue
- Move window, increasing
windowFreq[s2[right]]++
and decreasingwindowFreq[s2[left]]--
- If
Arrays.equals()
-> returntrue
- Return
false
O(n) time
O(1) space
Rotate List
Given the head
of a linked list, rotate the list to the right by rotations
places.
- Use
slow
andfast
runners - Compute
length
withfast
runner – old tail rotations = rotations % length
- If
rotations == 0
-> returnhead
- Move
slow
up toi < length - 1 - rotations
– new tail newHead = slow.next
slow.next = null
fast.next = head
- Return
newHead
O(n) time
O(1) space
Koko Eating Bananas
Koko loves to eat bananas. There are n
piles of bananas, the ith
pile has piles[i]
bananas. The guards have gone and will come back in h
hours.
Koko can decide her bananas-per-hour eating speed of k
. Each hour, she chooses some pile of bananas and eats k
bananas from that pile. If the pile has less than k
bananas, she eats all of them instead and will not eat any more bananas during this hour.
Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return.
Return the minimum integer k
such that she can eat all the bananas within h
hours.
- Use BS from
1
to eitherInteger.MAX_VALUE
ormax(piles)
- Use
canEatAll()
for eachmid
- Iterate
piles
:time += pile / speed + (pile % speed == 0) ? 0 : 1
- If
time > h
-> returnfalse
O(n log(Integer.MAX_VALUE)) time
O(1) space
Maximum Candies Allocated to K Children
You are given a 0-indexed integer array candies
. Each element in the array denotes a pile of candies of size candies[i]
. You can divide each pile into any number of sub piles, but you cannot merge two piles together.
You are also given an integer k
. You should allocate piles of candies to k
children such that each child gets the same number of candies. Each child can take at most one pile of candies and some piles of candies may go unused.
Return the maximum number of candies each child can get.
- Use BS from
0
to eitherInteger.MAX_VALUE
ormax(candies)
- Use
canAllocateToEverybody()
for eachmid
- Iterate
candies
:total += pile / candiesPerChild
- If
total >= k
-> returntrue
O(n log(Integer.MAX_VALUE)) time
O(1) space
Surrounded Regions
Given an m x n
matrix board
containing 'X'
and 'O'
, capture all regions that are 4-directionally surrounded by 'X'
.
A region is captured by flipping all 'O'
s into 'X'
s in that surrounded region.
- Use DFS to find graph components, starting from
O
- Save component as surrounded if it has no border connections
- Iterate
visited
again and flip surrounded components toX
O(m * n) time
O(m * n) space
Course Schedule II
There are a total of numCourses
courses you have to take, labeled from 0
to numCourses - 1
. You are given an array prerequisites
where prerequisites[i] = [ai, bi]
indicates that you must take course bi
first if you want to take course ai
.
Return the ordering of courses you should take to finish all courses. If there are many valid answers, return any of them. If it is impossible to finish all courses, return an empty array.
- Build adjacency list
- Run DFS to find cycles
- Push vertices to path stack if
visited[current] == 1
- Return reversed stack
O(n) time
O(n) space
Copy List with Random Pointer
A linked list of length n
is given such that each node contains an additional random pointer, which could point to any node in the list, or null
.
Construct a deep copy of the list. Return the head of the copied linked list.
- Iterate original list, create a copy of each node and add it to the
Map
- Create a new list with copied nodes
O(n) time
O(n) space
Rotate array
Given an integer array nums
, rotate the array to the right by k
steps, where k
is non-negative.
Use tmp[(i + k) % tmp.length] = nums[i]
OR
k = k % nums.length
- Reverse
[0; nums.length - 1]
- Reverse
[0; k - 1]
- Reverse
[k; nums.length - 1]
O(n) time
O(1) space
Binary Tree Inorder Traversal
t(left); add(); t(right);
OR
while (!stack.isEmpty() || root != null)
- If
root != null
->push(); root = root.left
- Else ->
root = poll(); add(); root = root.right
O(n) time
O(h) space
Binary Tree Preorder Traversal
add(); t(left); t(right);
OR
while (!stack.isEmpty() || root != null)
- If
root != null
->add(); push(); root = root.left
- Else ->
root = poll(); root = root.right
O(n) time
O(h) space
Binary Tree Postorder Traversal
t(left); t(right); add();
OR
- Use two
Stack
push(root)
while (!stack.isEmpty())
out.push();
- If
root.left != null
->push(root.left)
- If
root.right != null
->push(root.right)
- Reverse
out
O(n) time
O(h) space
Kth Smallest Element in a BST
Given the root
of a binary search tree, and an integer k
, return the kth
smallest value (1-indexed) of all the values of the nodes in the tree.
- Use iterative inorder traversal
- If
--k == 0
-> returnroot.val
O(h + k) time
O(h) space
Binary Search Tree Iterator
Implement the BSTIterator
class that represents an iterator over the in-order traversal of a binary search tree (BST):
-
boolean hasNext()
– returnstrue
if there exists a number in the traversal to the right of the pointer, otherwise returnsfalse
-
int next()
– moves the pointer to the right, then returns the number at the pointer
-
hasNext()
-> return!stack.isEmpty() || current != null
-
next()
-> iterative inorder traversal withwhile (current != null)
loop
O(1) on average time
O(h) space
Construct Binary Tree from Preorder and Inorder Traversal
Given two integer arrays preorder
and inorder
where preorder
is the preorder traversal of a binary tree and inorder
is the inorder traversal of the same tree, construct and return the binary tree.
- Convert
inorder
to value-to-indexMap
- Init
preorderRootIdx = 0
- Use recursive
toTree(preorder, left, right)
- If
left > right
-> returnnull
Node root = new Node(preorder[preorderRootIdx++])
root.left = toTree(preorder, left, map.get(root.val) -1)
root.right = toTree(preorder, map.get(root.val) + 1, right)
- Return
root
O(n) time
O(n) space
Set Matrix Zeroes
Given an m x n
integer matrix matrix
, if an element is 0
, set its entire row and column to 0
’s.
Use two Set
to store zeroed rows and cols
OR
- Init two flags
isFirstRowZeroed
andisFirstColZeroed
- Iterate
matrix
fromi = 1; j = 1
and use first col and row cells to mark zeroed ones - Iterate
matrix
again to set zeroes - If flags from (1) are
true
-> set zeroes in first row and/or col
O(m * n) time
O(1) space
Swap Nodes in Pairs
Given a linked list, swap every two adjacent nodes and return its head. You must solve the problem without modifying the values in the list’s nodes (i.e., only nodes themselves may be changed.)
- Create
dummy
node - Start from the
current = head
andprev = dummy
while (current != null && current.next != null)
- Relink, updating
current
andprev
- Return
dummy.next
O(n) time
O(1) space
Kth Largest Element in an Array
Given an integer array nums
and an integer k
, return the kth
largest element in the array.
Note that it is the kth
largest element in the sorted order, not the kth
distinct element.
You must solve it in O(n)
time complexity.
- Use recursive
quickSelect(nums, left, right, k)
- If
partition == k - 1
-> return nums[partition]` - If
partition > k - 1
-> returnquickSelect(nums, left, partition - 1, k)
- Else -> return
quickSelect(nums, partition + 1, right, k)
- Use
partition(nums, left, right)
pivot = nums[right]; pivotPointer = left
- Iterate
[left; right)
- If
nums[i] > pivot
->swap(i, pivotPointer); pivotPointer++
swap(right, pivotPointer)
- Return
pivotPointer
O(n) time on average // n/2 + n/4 + ...
O(n) space
3Sum Closest
Given an integer array nums
of length n
and an integer target
, find three integers in nums such that the sum is closest to target
.
Return the sum of the three integers.
- Use three pointers
i = [0; N - 2); left = i + 1; right = N - 1
- If
abs(sum - target) < minDiff
-> updateminDiff
andclosestSum
- Return
closestSum
O(n) time
O(1) space
Decode String
Given an encoded string, return its decoded string.
The encoding rule is: k[encoded_string]
, where the encoded_string
inside the square brackets is being repeated exactly k
times. Note that k
is guaranteed to be a positive integer.
- Use two stacks:
numsStack
andvaluesStack
- Init
currentNum = 0
andvaluesStack.push(new StringBuilder())
- If digit ->
currentNum = currentNum * 10 + digit
- If
[
->valuesStack.push(new StringBuilder); numsStack.push(currentNum); currentNum = 0
- If
]
->valuesStack.peek().append(newValue)
- Else ->
valuesStack.peek().append(c)
- Return
valuesStack.pop().toString()
O(n) time
O(n) space
Minimum Height Trees
A tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.
Given a tree of n
nodes labelled from 0
to n - 1
, and an array of n - 1
edges where edges[i] = [ai, bi]
indicates that there is an undirected edge between the two nodes ai
and bi
in the tree, you can choose any node of the tree as the root. When you select a node x
as the root, the result tree has height h
. Among all possible rooted trees, those with minimum height (i.e. min(h)
) are called minimum height trees (MHTs).
Return a list of all MHTs’ root labels. You can return the answer in any order.
The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.
- Build
adjList
- Find all
leaves
:adjList.get(i).size() == 1
while (N > 2)
- Remove all leaves
- If
adjList.get(i).size() == 1
->newLeaves.add(i)
N -= leaves
leaves = newLeaves
- Return
leaves
O(n) time
O(n) space
Contiguous Array
Given a binary array nums
, return the maximum length of a contiguous subarray with an equal number of 0
and 1
.
- Use
Map<Integer, Integer> prefixSum
sum += nums[i] == 0 ? -1 : 1
- If
sum ==0
->maxLength = i + 1
- If
prefixSum.containsKey(sum)
->maxLength = max(maxLength, i - prefixSum.get(sum)
- Else ->
prefixSum.put(sum, i)
- Return
maxLength
O(n) time
O(n) space
Maximum Size Subarray Sum Equals K
Given an array nums
and a target value k
, find the maximum length of a subarray that sums to k
. If there isn’t one, return 0
instead.
- Use
Map<Integer, Integer> prefixSum
sum += nums[i]
- If
sum == k
->maxLength = i + 1
- If
prefixSum.containsKey(sum - k)
->maxLength = max(maxLength, i - prefixSum(sum - k)
- Else ->
prefixSum.put(sum, i)
- Return
maxLength
O(n) time
O(n) space
Find K Closest Elements
Given a sorted integer array arr
, two integers k
and x
, return the k
closest integers to x
in the array. The result should also be sorted in ascending order.
An integer a
is closer to x
than an integer b
if:
|a - x| < |b - x|
, or|a - x| == |b - x|
and a < b
Use maxHeap
OR
- Use BS for
[0; N - k]
- If
x > (arr[mid] + arr[mid + k]) / 2.0
->left = mid + 1
- Else ->
right = mid
- Return
[left; left + k)
O(log n) time
O(k) space
Asteroid Collision
We are given an array asteroids
of integers representing asteroids in a row.
For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed.
Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.
- Use
Stack
- If
asteroid > 0
->push()
- Else
- While
!isEmpty && peek() > 0 && peek() < -asteroid
->pop()
- If
isEmpty || peek() < 0
->push()
- If
peek() == -asteroid
->pop()
- Return reversed
Stack
O(n) time
O(n) space
Merge k Sorted Lists
You are given an array of k
linked-lists lists
, each linked-list is sorted in ascending order.
Merge all the linked-lists into one sorted linked-list and return it.
- Use
minHeap
of roots - Init
Node dummy; Node current = dummy
current.next = minHeap.poll()
current = current.next
- If
current.next != null
->minHeap.offer()
- Return
dummy.next
O(nlog k) time
O(k) space
LRU Cache
Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.
-
LRUCache(int capacity)
- Initialize the LRU cache with positive size capacity. -
int get(int key)
- Return the value of the key if the key exists, otherwise return-1
. -
void put(int key, int value)
- Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.
The functions get and put must each run in O(1)
average time complexity.
- Use
Map<Integer, Node> keyToNode
- Implement doubly-linked list, using
dummyHead
anddummyTail
- On each “touch”
remove()
node andaddToHead()
- If
capacity == size()
->removeTail()
O(1) time
O(n) space
Binary Tree Zigzag Level Order Traversal
Given the root
of a binary tree, return the zigzag level order traversal of its nodes’ values. (i.e., from left to right, then right to left for the next level and alternate between).
- Use BST for level traversal
- On each level switch
isLeft = !isLeft
to change direction - If
isLeft
->add(val)
- Else ->
add(0, val)
O(n) time
O(n) space
All Nodes Distance K in Binary Tree
Given the root
of a binary tree, the value of a target node target
, and an integer k
, return an array of the values of all nodes that have a distance k
from the target
node.
- Build
Map<Node, Node> nodeToParent
to be able to treat the tree as a graph - Use BFS for level traversal (don’t forget
Set<Node> visited
) - If
level == k
-> returnQueue
with all the nodes from this level level++
- If
visited.add()
-> offerleft
,right
andparent
- Return
List.of()
O(n) time
O(n) space
All Paths From Source to Target
Given a directed acyclic graph (DAG) of n
nodes labeled from 0
to n - 1
, find all possible paths from node 0
to node n - 1
and return them in any order.
The graph is given as follows: graph[i]
is a list of all nodes you can visit from node i
(i.e., there is a directed edge from node i
to node graph[i][j]
).
- Use recursive
dfs(graph, start, currentPath, result)
- If
start == graph.length - 1
->add()
and return - Run
dfs
for all children
O(2^n) time
O(2^n) space
Palindrome Partitioning
Given a string s
, partition s
such that every
substring of the partition is a palindrome. Return all possible palindrome partitioning of s
.
- Use recursive
backtrack(s, start, currentPartition, result)
- If
start == s.length
->add()
and return - For
end = [start; length)
- If
!isPalindrome
-> continue backtrack(s, end + 1, currentPartition.add(s.substring(start, end + 1)))
O(2^n) time
O(2^n) space
Combinations
Given two integers n
and k
, return all possible combinations of k
numbers chosen from the range [1, n]
.
- Use recursive
backtrack(nums, start, currentCombination, k, result)
- If
size() == k
->add()
and return backtrack(nums, start + 1)
O(2^n) time
O(k) space
Combination Sum III
Find all valid combinations of k
numbers that sum up to n
such that the following conditions are true:
- Only numbers
1
through9
are used. - Each number is used at most once.
Return a list of all possible valid combinations. The list must not contain the same combination twice, and the combinations may be returned in any order.
- Use recursive
backtrack(nums, start, currentCombination, remains, k, result)
- If
remains < 0
-> return - If
size() == k && remains ==0
->add()
and return backtrack(nums, start + 1)
O(2^9) time
O(k) space
Target Sum
You are given an integer array nums
and an integer target
.
You want to build an expression out of nums by adding one of the symbols '+'
and '-'
before each integer in nums
and then concatenate all the integers.
For example, if nums = [2, 1]
, you can add a '+'
before 2
and a '-'
before 1
and concatenate them to build the expression "+2-1"
.
Return the number of different expressions that you can build, which evaluates to target
.
- Use recursive
count(nums, start, currentSum, targetSum, memo)
- If
start == length() && current == target
-> return1
else0
- Check and add to
memo
:start + ":" + current
, because with negative numbers we can have the same sum on different steps - Return
count(+) + count(-)
O(target * n) time
O(target * n) space
Combination Sum IV
Given an array of distinct integers nums
and a target integer target
, return the number of possible combinations that add up to target
.
- Use recursive
count(nums, remains, memo)
- If
remains < 0
-> return0
- If
remains == 0
-> return1
- Check and add to
memo
:remains
- For each
nums
->count(remains - num)
- Return
count
O(target * n) time
O(target * n) space
If negative numbers are allowed, we should limit the max length because of possible loops. We also should use length + remains
as a key, because we can have the same sum on different steps.
Non-overlapping Intervals
Given an array of intervals intervals
where intervals[i] = [starti, endi]
, return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.
- Sort by start
nonOverlappingIntervalscount = 1
- If
current.start >= end
->end = current.end; count++
- Else -> end = min(end, current.end)`
- Return
length() - count
O(nlog n) time
O(1) space
Count Good Nodes in Binary Tree
Given a binary tree root
, a node X
in the tree is named good if in the path from root
to X
there are no nodes with a value greater than X
.
Return the number of good nodes in the binary tree.
- Use recursive
count(root, max)
- If
root == null
-> return0
- Update
max
current = root.val >= max ? 1 : 0
- Return
current + left + right
O(n) time
O(h) space
Meeting Rooms II
Given an array of meeting time intervals
consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei)
, find the minimum number of conference rooms required.
- Create
starts
andends
array and sort them - Use two pointers
startPointer
andendPointer
while (startPointer < starts.length())
- If
starts[s] < ends[e]
->busyCount++; s++
- Else ->
busyCount--; e++
- Update
maxCount
- Return
maxCount
O(nlog n) time
O(n) space
Interval List Intersections
You are given two lists of closed intervals, firstList
and secondList
, where firstList[i] = [starti, endi]
and secondList[j] = [startj, endj]
. Each list of intervals is pairwise disjoint and in sorted order.
Return the intersection of these two interval lists.
The intersection of two closed intervals is a set of real numbers that are either empty or represented as a closed interval. For example, the intersection of [1, 3]
and [2, 4]
is [2, 3]
.
- Use two pointers
while (f < first.length() && s < second.length())
- If
firstInterval.start <= secondInterval.end && secondInterval.start <= firstInterval.end
->add(max, min)
- If
firstInterval.end <= secondInterval.end
->f++
- Else ->
s++
- Return
intersections
O(n) time
O(n) space
Sum Root to Leaf Numbers
You are given the root of a binary tree containing digits from 0
to 9
only.
Each root-to-leaf path in the tree represents a number.
For example, the root-to-leaf path 1 -> 2 -> 3
represents the number 123
.
Return the total sum of all root-to-leaf numbers.
- Use recursive
sum(root, sum)
- If
root == null
-> return0
sum = sum * 10 + root.val
- If
left == null && right == null
-> returnsum
- Return
sum(left) + sum(right)
O(n) time
O(h) space
Remove Duplicates from Sorted Array
Given an integer array nums
sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once. The relative order of the elements should be kept the same.
Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums
. More formally, if there are k
elements after removing the duplicates, then the first k
elements of nums should hold the final result. It does not matter what you leave beyond the first k
elements.
Return k
after placing the final result in the first k
slots of nums.
Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.
- Iterate
[1; N)
- If
nums[i] != nums[i - 1]
->nums[pointer++] = nums[i]
- Return
pointer
O(n) time
O(1) space
Merge Sorted Array
You are given two integer arrays nums1
and nums2
, sorted in non-decreasing order, and two integers m
and n
, representing the number of elements in nums1
and nums2
respectively.
Merge nums1
and nums2
into a single array sorted in non-decreasing order.
The final sorted array should not be returned by the function, but instead be stored inside the array nums1
. To accommodate this, nums1
has a length of m + n
, where the first m
elements denote the elements that should be merged, and the last n
elements are set to 0
and should be ignored. nums2
has a length of n
.
- Use three pointers, iterating backwards:
first
,second
andresult
while (second >= 0)
- If
first >= 0 && nums1[first] >= nums2[second]
->nums1[result--] = nums1[first--]
- Else ->
nums1[result--] = nums2[second--]
O(n) time
O(1) space
Sort List
Given the head
of a linked list, return the list after sorting it in ascending order.
- Use Merge Sort
- Recursive
sort(root)
mid = findMid(root)
left = sort(root)
right = sort(mid)
- Return
merge(left, right)
O(nlog n) time
O(log n) space
Basic Calculator II
Given a string s
which represents an expression, evaluate this expression and return its value:
+
-
*
/
- Use
Stack
prevOperator = '+'
- If
isDigit()
->currentVal = currentVal * 10 + currentChar
- Else ->
eval(); currentVal = 0; prevOperator = currentChar
-
eval()
the last integer in the expression -
eval()
:+
->push(currentValue)
;-
->push(-currentValue)
;*
->push(pop() * currentValue)
- Sum up elements in the
Stack
O(n) time
O(n) space
Basic Calculator
Given a string s
representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation:
+
-
(
)
- Use
Stack
sign = 1
- If
isDigit()
->currentVal = currentVal * 10 + currentChar
- Else ->
result += currentVal * sign
- If
+
->sign = 1
- If
-
->sign = 0
- If
(
->push(result); push(sign); result = 0; sign = 1
- If
)
->result = result * pop() + pop()
- Return
result
O(n) time
O(n) space
String to Integer (atoi)
Implement the myAtoi(string s)
function, which converts a string to a 32-bit signed integer (similar to C/C++’s atoi function).
- Check if
s
is empty - Trim whitespaces
- Check if
s
is empty - Check
+
/-
sign - Iterate
result = result * 10 + currentChar
- Check for overflow
- Return
(int) result * sign
O(n) time
O(1) space
Largest Number
Given a list of non-negative integers nums
, arrange them such that they form the largest number and return it.
- Convert to
String[] arr
- Sort
(a + b).compareTo(b + a)
- Return
String.join("", arr)
- Prove transtransitivity property: if
AB > BA
andBC > CB
thanAC > CA
O(nlog n) time
O(n) space