Introduction
Practice Interviews!
A collection of 75 of the best leetcode questions to do.
If you have an interview soon, do the Most Important Problems.
If you want general practice, we have General Conceptual Problems you can practice!
Download these problems as an Anki text file! This allows you do to spaced repetition and find the best timing to learn and practice problems, especially those you forget.
Ever forget Python syntax, or a common data structure in Python? We have a Python Interview Cheat Sheet.
Python Data Structures Cheat Sheet
Lists
lst = []
lst = [3, 2, 7, 5]
lst = [i for i in range(10)] # comprehensions
lst = [0 for _ in range(10)]
lst = []
lst[5] # IndexError out of range
lst = [3, 2, 7, 5]
val = lst[3]
print(val) # 5
lst[3] = 2
print(lst[3]) # 2
lst = [None, True, 2, "Hello"]
lst.append(4)
lst.extend([3, True])
lst.insert(2, "yeet")
lst.remove(True) # finds first and remove
list.pop() # last elm
list.pop(2) # second elm
list.sort() # key=None, reverse=False, ALSO in place
list.reverse() # in place
# iterate list backwards
for i in range(len(list) - 1, -1, -1):
print(i)
2D Arrays
# can be different size rows, most times same for a rectangle matrix
arr = [[0, 1, 2],
[3, 4, 5],
[6, 7, 8]]
arr = [[j for j in range(3 * i, 3 * i + 3)] for i in range(3)]
# first for which row, second for where in row
print(arr[0][0]) # 0
print(arr[0][2]) # 2
print(arr[2][0]) # 6
print(arr[2][2]) # 8
for y in range(len(arr)):
for x in range(len(arr[y])):
print(arr[y][x])
Stacks
# using deque
from collections import deque
stack = deque()
stack.append(5)
stack.pop()
print(stack[-1]) # peek
# using list
stack = []
stack.append(5) # push
stack.pop() # pop
print(stack[-1]) # peek
# both
while len(stack) != 0:
val = stack.pop()
# Stack is visualized as a vertical structure and hence has depth - DFS.
Queues
# using deque
from collections import deque
queue = deque()
queue.append(5) # push right
queue.popleft() # pop left
print(queue[-1]) # peek
# using list (not recommended)
queue = []
queue.append(5) # push right
queue.pop(0) # pop left
print(stack[-1]) # peek
# both
while len(queue) != 0:
val = queue.pop()
# Queue can be generally thought as horizontal in structure i.e, breadth/width can be attributed to it - BFS.
Priority Queue
import heapq
q = []
heapq.heappush(q, (2, 'code')) # priority based on first value
heapq.heappush(q, (1, 'eat'))
heapq.heappush(q, (3, 'sleep'))
while q:
next_item = heapq.heappop(q)
print(next_item)
# Result:
# (1, 'eat')
# (2, 'code')
# (3, 'sleep')
is_empty = len(q) == 0
# uses heaps, which are implemented as Python List
Dicts/HashMap
m = {}
# or
m = dict()
m = {
2 : "Hello",
"ee" : "TSM"
}
m[3] = True
m["Hello"] = 1
m[False] = None
a = m[3]
b = m[4] # KeyError
in_key_set = 3 in m # True in KeySet
len(m) # num elm
is_empty = len(m) == 0
m[9] += 1 # KeyError
if 9 in m:
m[9] += 1
else:
m[9] = 1
for k in m:
v = m[k]
print("k: %s, v: %s" % (k, v))
for k, v in m.items():
print("k: %s, v: %s" % (k, v))
m.keys() # dict_keys([2, 'ee', ...])
m.values() # dict_values(['Hello', 'TSM', ..])
Sets
s = set()
s.add(5)
in_set = 3 in s
s.pop(5)
len(s) # num elm
is_empty = len(s) == 0
# intersect AND, union OR, ^ XOR
Tuples
t = ()
t = (1, 5)
t = (3, "eh", True)
a, b, c = (3, "eh", True)
def a():
return (5, 2)
x, y = a()
tuple_contains = 5 in t
is_empty = len(t) == 0
Linked List
Simple
class LinkNode:
def __init__(self, data):
self.data = data
self.next = None
a = LinkNode(5) # [5, null]
b = LinkNode(6)
c = LinkNode(7)
a.next = b # [5, -]-> [6, null]
b.next = c # [5, -]-> [6, -]-> [7, null]
cur = a # pointer
while cur != None:
print(cur.data)
cur = cur.next
# alt build backwards
a2 = LinkNode(7) # [7, null]
temp = LinkNode(6)
temp.next = a2
a2 = temp # [6, -]-> [7, null]
temp = LinkNode(5)
temp.next = a2
a2 = temp # [5, -]-> [6, -]-> [7, null]
# alt build with pointer from front
a3 = LinkNode(5)
a3.next = LinkNode(6)
a3.next.next = LinkNode(7)
# alt build step by step
a4 = LinkNode(5)
cur = a4
cur.next = LinkNode(6)
cur = cur.next
cur.next = LinkNode(7)
Head Pointer Deque (Stack and/or Queue)
class LinkedDeque:
def __init__(self):
self.head = None
def add_front(self, data):
temp = LinkNode(data)
temp.next = self.head
self.head = temp
def add_back(self, data):
if self.head == None:
self.head = LinkNode(data)
else:
ptr = self.head
while ptr.next != None:
ptr = ptr.next
ptr.next = LinkNode(data)
def remove_front(self):
if self.head == None:
raise Exception("nothing to remove")
else:
self.head = self.head.next
def remove_back(self):
if self.head == None:
raise Exception("nothing to remove")
else:
if self.head.next == None:
self.head = None
else:
ptr = self.head
while ptr.next.next != None:
ptr = ptr.next
ptr.next = None
Using Dummy Head
class LinkedDeque:
def __init__(self):
self.head = link_node(None)
def add_front(self, data):
temp = link_node(data)
temp.next = self.head.next
self.head.next = temp
def add_back(self, data):
ptr = self.head
while ptr.next != None:
ptr = ptr.next
ptr.next = link_node(data)
def remove_front(self):
if self.head.next == None:
raise Exception("nothing to remove")
else:
self.head.next = self.head.next.next
def remove_back(self):
if self.head.next == None:
raise Exception("nothing to remove")
else:
if self.head.next.next == None:
self.head.next = None
else:
ptr = self.head.next
while ptr.next.next != None:
ptr = ptr.next
ptr.next = None
Double Linked List with Head and Tail: Deque
class DLinkNode():
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
class DLinkedDeque():
def __init__(self):
self.head = None
self.tail = None
def add_front(self, data):
if self.head == None:
self.head = DLinkNode(data)
self.tail = self.head
else:
temp = DLinkNode(data)
temp.next = self.head
self.head.prev = temp
self.head = temp
def add_back(self, data):
if self.head == None:
self.head = DLinkNode(data)
self.tail = self.head
else:
temp = DLinkNode(data)
self.tail.next = temp
temp.prev = self.tail
self.tail = temp
def remove_front(self):
if self.head == None:
raise Exception("nothing to remove")
else:
self.head.next = None
self.head = self.head.next
def remove_back(self):
if self.head == None:
raise Exception("nothing to remove")
else:
self.tail.prev.next = None
self.tail = self.tail.prev
Linked List as a List
Double Linked generalizes
class LinkedList():
# a = LinkedList()
def __init__(self):
self.head = None
self.size = 0 # don't need can also choose to recalc
# len(a)
def __len__(self):
return self.size
# a[x] = c
def __setitem__(self, data, index):
if x > self.size:
raise Exception("out of bounds")
if self.head == None: # x must equal 0 as size is 0
self.head = LinkNode(data)
self.size += 1
else if x == 0: # size does not equal 0
temp = LinkNode(data)
temp.next = self.head.next
self.head = temp
self.size += 1
else: # insert normally into list
ptr = self.head
for i in range(x - 1): # x >= 1
ptr = ptr.next
temp = LinkNode(data)
temp.next = ptr.next
ptr.next = temp
self.size += 1
# b = a[x]
def __getitem__(self, index):
if x >= self.size:
raise Exception("out of bounds")
ptr = self.head
for i in range(self.size):
if i == index:
return ptr.data
ptr = ptr.next
# del a[x]
def __delitem__(self, index)
if x >= self.size:
raise Exception("out of bounds")
if self.size == 1: # x must be 0
self.head = None
self.size -= 1
else:
for i in range(self.size - 1):
if i + 1 == index:
ptr.next = ptr.next.next
self.size -= 1
return
ptr = ptr.next
Circular
a = LinkNode(5)
a.next = LinkNode(6)
a.next.next = LinkNode(7)
a.next.next.next = a # to front
# no None end
Dict to LinkedList (LRU Cache)
Description: want to map a -> b but store order b is inserted Create link(b) front on stack, most recently used map a -> link(b)
Trees
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.val = key
DFS
# A function to do inorder tree traversal
def printInorder(node):
if not node:
return
# First recur on left child
printInorder(node.left)
# then print the data of node
print(node.val)
# or do action at this node
# now recur on right child
printInorder(node.right)
'''
preorder:
print(node.val)
printInorder(node.left)
printInorder(node.right)
postorder
printInorder(node.left)
printInorder(node.right)
print(node.val)
'''
BFS
def printLevelOrder(root):
# Base Case
if root is None:
return
# Create an empty queue for level order traversal
queue = []
# Enqueue Root and initialize height
queue.append(root)
while queue:
# Print front of queue and remove it from queue
print(queue[0].val)
# or do action with this node
node = queue.pop(0)
#Enqueue left child
if node.left is not None:
queue.append(node.left)
# Enqueue right child
if node.right is not None:
queue.append(node.right)
#Driver Program to test above function
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
print("Level Order Traversal of binary tree is -")
printLevelOrder(root)
#This code is contributed by Nikhil Kumar Singh(nickzuck_007)
A common pattern is to use a set()
visited to ignore where you have visited.
BFS guarantees finding the shortest path first while DFS might find longer paths before finding the shortest one.
Dijkstra's algorithm
import heapq
class GenericSearch:
def __init__(self, graph):
self.graph = graph
def dijkstra_search(self, start, goal):
open_set = []
heapq.heappush(open_set, (0, start))
came_from = {}
cost_so_far = {start: 0}
while open_set:
current_cost, current = heapq.heappop(open_set)
if current == goal:
path = []
while current in came_from:
path.append(current)
current = came_from[current]
path.append(start)
return path[::-1]
for neighbor in self.graph[current]:
new_cost = cost_so_far[current] + self.graph[current][neighbor]
if neighbor not in cost_so_far or new_cost < cost_so_far[neighbor]:
cost_so_far[neighbor] = new_cost
came_from[neighbor] = current
heapq.heappush(open_set, (new_cost, neighbor))
return None # No path found
# Example graph
graph = {
'A': {'B': 1, 'C': 3},
'B': {'D': 5, 'E': 7},
'C': {'F': 2},
'D': {},
'E': {'F': 1},
'F': {}
}
# Example usage
search = GenericSearch(graph)
print("Dijkstra Search:", search.dijkstra_search('A', 'F'))
A* search algorithm
import heapq
class GenericSearch:
def __init__(self, graph):
self.graph = graph
def heuristic(self, node, goal):
return 0
def a_star_search(self, start, goal):
open_set = []
heapq.heappush(open_set, (0, start))
came_from = {}
g_score = {node: float('inf') for node in self.graph}
g_score[start] = 0
f_score = {node: float('inf') for node in self.graph}
f_score[start] = self.heuristic(start, goal)
while open_set:
current = heapq.heappop(open_set)[1]
if current == goal:
path = []
while current in came_from:
path.append(current)
current = came_from[current]
path.append(start)
return path[::-1]
for neighbor in self.graph[current]:
tentative_g_score = g_score[current] + self.graph[current][neighbor]
if tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score[neighbor] = tentative_g_score + self.heuristic(neighbor, goal)
if neighbor not in [node[1] for node in open_set]:
heapq.heappush(open_set, (f_score[neighbor], neighbor))
return None # No path found
# Example graph
graph = {
'A': {'B': 1, 'C': 3},
'B': {'D': 5, 'E': 7},
'C': {'F': 2},
'D': {},
'E': {'F': 1},
'F': {}
}
# Example usage
search = GenericSearch(graph)
print("A* Search:", search.a_star_search('A', 'F'))
Tries
# make trie
trie = {}
for w in words:
t = trie
for c in w:
if c not in t:
t[c] = {}
t = t[c]
t['#'] = '#'
Graphs
# Definition for a Node for a Graph.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
Most Important Problems!
Jeremy Aguilon's Ranking Interview Questions by Cram Score
Level 1: Interview Tomorrow 😫
Number of Islands
Given a 2-D Array, count the number of islands in it, where land is connected in the NSEW direction. Tags: Recursion, Search, Union-Find
Try It!
Discussion
Video
Solution
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1':
self.dfs_marking(grid, i, j);
count += 1
return count
def dfs_marking(self, grid, i, j):
if i < 0 or i >= len(grid):
return
if j < 0 or j >= len(grid[0]):
return
if grid[i][j] != '1':
return
grid[i][j] = '0'
self.dfs_marking(grid, i + 1, j)
self.dfs_marking(grid, i - 1, j)
self.dfs_marking(grid, i, j + 1)
self.dfs_marking(grid, i, j - 1)
Coin Change
Given a target of N cents and a collection of coins, how many ways can you form N cents? Tags: Dynamic Programming, Recursion
Try It!
Discussion
Video
Solution
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float('inf') for i in range(amount + 1)]
dp[0] = 0
for i in range(1, amount + 1):
for coin in coins:
if i - coin >= 0 and dp[i - coin] + 1 < dp[i]:
dp[i] = dp[i - coin] + 1
if dp[amount] == float('inf'):
return -1
return dp[amount]
Minimum Window Substring
Given a string and a collection of characters, find the shortest substring that contains all the characters. Tags: Sliding Window
Try It!
Discussion
Video
Solution
class Solution:
def minWindow(self, s: str, t: str) -> str:
t_counter = collections.Counter(t)
t_needed = len(t)
left = 0
right = 0
min_len = float('inf')
min_str = ''
while right < len(s):
c_right = s[right]
if c_right in t_counter:
count = t_counter[c_right]
if count > 0:
t_needed -= 1
t_counter[c_right] -= 1
while t_needed == 0:
c_left = s[left]
if c_left in t_counter:
count = t_counter[c_left]
if count == 0:
t_needed += 1
t_counter[c_left] += 1
if right - left + 1 < min_len:
min_len = right - left + 1
min_str = s[left:right + 1]
left += 1
right += 1
return min_str
Buying and Selling Stock
Given a list of starting and ending days for a stock, maximize your profit Tags: Greedy
Try It!
Discussion
Video
Solution
class Solution:
def maxProfit(self, prices: List[int]) -> int:
lowest = prices[0]
max_gain = 0
for i in range(1, len(prices)):
price = prices[i]
if price - lowest > max_gain:
max_gain = price - lowest
if price < lowest:
lowest = price
return max_gain
Range Sum Query (Deprecated)
Efficiently compute the sum of the numbers between two indexes of an array. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class NumArray:
def __init__(self, nums: List[int]):
for i in range(1, len(nums)):
nums[i] += nums[i - 1]
self.sum = nums
def sumRange(self, i: int, j: int) -> int:
if i == 0:
return self.sum[j]
else:
return self.sum[j] - self.sum[i - 1]
Merge Intervals
Given a list of intervals with a start and end value, merge the intervals. Tags: Sorting
Try It!
Discussion
Video
Solution
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
ans = []
if len(intervals) < 2:
return intervals
intervals.sort(key=lambda x: x[0])
cur = intervals[0]
for i in range(len(intervals)):
interval = intervals[i]
if cur[1] >= interval[0]:
cur[1] = max(cur[1], interval[1])
else:
ans.append(cur)
cur = interval
ans.append(cur)
return ans
Maximum Subarray
Given an array, find the subarray with the maximum sum. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
ans = nums[0]
cur_total = 0
for n in nums:
cur_total += n
ans = max(ans, cur_total)
if cur_total < 0:
cur_total = 0
return ans
Level 2: Week to Prepare 😬
Range Sum Query Mutable (Deprecated)
Given a mutable array of integers, find the sum of elements between i and j. Tags: Recursion, Trees
Try It!
Discussion
Video
Solution
class Node:
def __init__(self, start, end):
self.start = start
self.end = end
self.total = 0
self.left = None
self.right = None
class NumArray:
def __init__(self, nums: List[int]):
def create_tree(self, start, end):
if start > end:
return None
elif start == end:
node = Node(start, end)
node.total = nums[start]
return node
else:
mid = start + (end - start) // 2
node = Node(start, end)
node.left = create_tree(nums, start, mid)
node.right = create_tree(nums, mid + 1, end)
node.total = node.left.total + node.right.total
return node
self.root = create_tree(nums, 0, len(nums) - 1)
def update(self, index: int, val: int) -> None:
def update_val(node, index, val):
if node.start == node.end:
node.total = val
return
mid = node.start + (node.end - node.start) // 2
if index <= mid:
update_val(node.left, index, val)
else:
update_val(node.right, index, val)
node.total = node.left.total + node.right.total
update_val(self.root, index, val)
def sumRange(self, left: int, right: int) -> int:
def sum_range(node, i, j):
if node.start == i and node.end == j:
return node.total
mid = node.start + (node.end - node.start) // 2
if j <= mid:
return sum_range(node.left, i, j)
elif i > mid:
return sum_range(node.right, i, j)
else:
return sum_range(node.left, i, mid) + sum_range(node.right, mid + 1, j)
return sum_range(self.root, left, right)
# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# obj.update(index,val)
# param_2 = obj.sumRange(left,right)
Word Search II (Deprecated)
Given a 2-D array of characters and a list of valid words, find the number of words on the board. Tags: Recursion, Search, Trees
Try It!
Discussion
Video
Solution
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
visited = [[False for c in range(len(board[0]))] for r in range(len(board))]
ans = set()
trie = {}
for word in words:
level = trie
for letter in word:
if letter not in level:
level[letter] = {}
level = level[letter]
level['#'] = '#'
for r in range(len(board)):
for c in range(len(board[0])):
cur = ''
self.dfs(board, visited, r, c, trie, cur, ans)
return list(ans)
def dfs(self, board, visited, r, c, trie, cur, ans):
if '#' in trie:
ans.add(cur)
if r < 0 or r >= len(board):
return
if c < 0 or c >= len(board[0]):
return
if visited[r][c]:
return
if board[r][c] not in trie:
return
letter = board[r][c]
if letter in trie:
cur += letter
trie = trie[letter]
visited[r][c] = True
self.dfs(board, visited, r + 1, c, trie, cur, ans)
self.dfs(board, visited, r - 1, c, trie, cur, ans)
self.dfs(board, visited, r, c + 1, trie, cur, ans)
self.dfs(board, visited, r, c - 1, trie, cur, ans)
visited[r][c] = False
Task Scheduler
Given an array of tasks an a cooldown period, given an efficient ordering. Tags: Greedy, Priority Queue
Try It!
Discussion
Video
Solution
class Solution:
def leastInterval(self, tasks: List[str], n: int) -> int:
task_counter = {}
for task in tasks:
if task not in task_counter:
task_counter[task] = 0
task_counter[task] += 1
# -count is the way to create max-heap in python. The heapq default is min-heap.
max_heap = []
for task in task_counter:
count = task_counter[task]
heapq.heappush(max_heap, -count)
tot_count = 0
while max_heap:
task_counts = []
for i in range(n + 1):
if max_heap:
count = heapq.heappop(max_heap)
task_counts.append(count)
for task_count in task_counts:
if task_count < -1: # if task_count is equal to -1, it is being used.
heapq.heappush(max_heap, task_count + 1)
if max_heap:
tot_count += n + 1 # + 1 due to difference in indexing +1 for spacing
else:
tot_count += len(task_counts)
return tot_count
Non-overlapping Intervals (Deprecated)
Given a collection of intervals, find the number of intervals you need to remove to make the rest of the intervals non-overlapping. Tags: Greedy, Sorting
Try It!
Discussion
Video
Solution
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
intervals.sort(key=lambda x: x[0])
count = 0
prev = intervals[0]
for i in range(1, len(intervals)):
cur = intervals[i]
if prev[1] > cur[0]:
count += 1
prev[1] = min(prev[1], cur[1])
else:
prev = cur
return count
Preorder Serialization Verification of a Binary Tree (Deprecated)
Given a particular kind of preorder serialization of a binary tree, verify that it's valid. Tags: Recursion, Trees
Try It!
Discussion
Video
Solution
class Solution:
def isValidSerialization(self, preorder: str) -> bool:
# remember how many empty slots we have
# non-null nodes occupy one slot but create two new slots
# null nodes occupy one slot
preorder = preorder.split(',')
#initially we have one empty slot to put the root in it
count = 1
for node in preorder:
# no empty slot to put the current node
if count == 0:
return False
# a null node?
if node == '#':
# ocuppy slot
count -= 1
else:
# use a slot, create 2 new slots
count += 1
#we don't allow empty slots at the end
return count == 0
Level 3: Sixth Sense Problems 🧐
Find the Duplicate Number (Deprecated)
Find the duplicate number in an array AND use O(1) space. Tags: Search
Try It!
Discussion
Diagram
Video
As an anime video!
Solution
class Solution:
def findDuplicate(self, nums: List[int]) -> int:
hare = nums[0]
tortoise = nums[0]
while True:
hare = nums[nums[hare]]
tortoise = nums[tortoise]
if hare == tortoise:
break
ptr1 = nums[0]
ptr2 = tortoise
while ptr1 != ptr2:
ptr1 = nums[ptr1]
ptr2 = nums[ptr2]
return ptr1
Construct Binary Tree from Preorder and Inorder Traversal
Given the preorder and inorder serialization of a binary tree, construct a tree data structure. Tags: Recursion, Search, Trees
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not inorder:
return None
root = preorder.pop(0)
idx = inorder.index(root)
node = TreeNode(root)
node.left = self.buildTree(preorder, inorder[:idx])
node.right = self.buildTree(preorder, inorder[idx + 1:])
return node
Decode Ways (Deprecated)
Given an encoding from letters to numbers, count the number of ways to decode a string of numbers. Tags: Dynamic Programming, Recursion
Try It!
Discussion
Video
Solution
class Solution:
def numDecodings(self, s: str) -> int:
dp = [0 for i in range(len(s) + 1)]
dp[0] = 1
if 1 <= int(s[0]) <= 9:
dp[1] = 1
for i in range(2, len(s) + 1):
if 1 <= int(s[i - 1]) <= 9:
dp[i] += dp[i - 1]
if 10 <= int(s[i - 2:i]) <= 26:
dp[i] += dp[i - 2]
return dp[-1]
Jump Game II (Deprecated)
Given a non-negative integer array where each index represents the maxmimum you can iterate forward, minimize the number of jumps to reach the end of the array. Tags: Greedy
Try It!
Discussion
Video
Solution
class Solution:
def jump(self, nums: List[int]) -> int:
if len(nums) == 1:
return 0
reachable = 0
last_jump_idx = 0
count = 0
for i in range(len(nums)):
# use greedy strategy
reachable = max(reachable, i + nums[i])
if i == last_jump_idx:
last_jump_idx = reachable
count += 1
if last_jump_idx == len(nums) - 1:
# if we land on last index but don't include this case, we add an extra jump
return count
return count
Find the Edit Distance Between Two Words (Deprecated)
Given two words, find the minimum number of edits to mutate one word into the other. Tags: Dynamic Programming, Recursion
Try It!
Discussion
Video
Solution
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
dp = [[0 for x in range(len(word2) + 1)] for y in range(len(word1) + 1)]
for y in range(len(word1) + 1):
dp[y][0] = y
for x in range(len(word2) + 1):
dp[0][x] = x
for y in range(1, len(word1) + 1):
for x in range(1, len(word2) + 1):
if word1[y - 1] == word2[x - 1]:
dp[y][x] = dp[y - 1][x - 1]
else:
dp[y][x] = 1 + min([
dp[y - 1][x],
dp[y][x - 1],
dp[y - 1][x - 1],
])
return dp[len(word1)][len(word2)]
More Practice Problems
Top 75 Leetcode Problems
String
Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
chars_used = set()
l = 0
r = 0
max_len = 0
while r < len(s):
c_r = s[r]
if c_r not in chars_used:
chars_used.add(c_r)
if r - l + 1 > max_len:
max_len = r - l + 1
r += 1
else:
c_l = s[l]
chars_used.remove(c_l)
l += 1
return max_len
Longest Repeating Character Replacement
Find the length of the longest substring containing all repeating letters you can get after changing at most k characters. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
left = 0
right = 0
max_len = 0
max_count = 0
char_counter = {}
while right < len(s):
c = s[right]
if c not in char_counter:
char_counter[c] = 0
char_counter[c] += 1
max_count = max(max_count, char_counter[c])
while right - left + 1 - max_count > k:
c = s[left]
char_counter[c] -= 1
left += 1
max_len = max(max_len, right - left + 1)
right += 1
return max_len
Valid Anagram
Given two strings s and t, write a function to determine if t is an anagram of s. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
t_count = {}
for c in t:
if c not in t_count:
t_count[c] = 0
t_count[c] += 1
for c in s:
if c not in t_count:
return False
else:
t_count[c] -= 1
for c in t_count:
if t_count[c] != 0:
return False
return True
Group Anagrams
Given an array of strings, group anagrams together. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
groups = {}
for word in strs:
key = tuple(sorted(word))
if key not in groups:
groups[key] = []
groups[key].append(word)
return groups.values()
Valid Parentheses
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def isValid(self, s: str) -> bool:
pair = {
')': '(',
'}': '{',
']': '['
}
stack = []
for c in s:
if c in pair:
if not stack:
return False
top = stack.pop()
if top != pair[c]:
return False
else:
stack.append(c)
return len(stack) == 0
Valid Palindrome
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def isPalindrome(self, s: str) -> bool:
left = 0
right = len(s) - 1
while left < right:
while left < right and not s[left].isalnum():
left += 1
while left < right and not s[right].isalnum():
right -= 1
if s[left].lower() != s[right].lower():
return False
left += 1
right -= 1
return True
Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. Tags: String
Try It!
Discussion
Video
Solution
Dynamic Programming Solution
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False for j in range(n)] for i in range(n)]
ans = ''
# every string with one char is a palindrome
for i in range(n):
dp[i][i] = True
ans = s[i]
# upper dp
for start in range(n - 1, -1, -1):
for end in range(start + 1, n):
if s[start] == s[end]:
if end - start == 1 or dp[start + 1][end - 1]:
dp[start][end] = True
if end - start + 1 > len(ans):
ans = s[start:end + 1]
return ans
Expand from middle solution
class Solution:
def longestPalindrome(self, s: str) -> str:
max_len = 0
max_str = ''
for i in range(len(s)):
# odd
j = i
k = i
while j >= 0 and k < len(s) and s[j] == s[k]:
if k - j + 1 > max_len:
max_len = k - j + 1
max_str = s[j:k + 1]
j -= 1
k += 1
# even
j = i
k = i + 1
while j >= 0 and k < len(s) and s[j] == s[k]:
if k - j + 1 > max_len:
max_len = k - j + 1
max_str = s[j:k + 1]
j -= 1
k += 1
return max_str
Palindromic Substrings
Given a string, your task is to count how many palindromic substrings in this string. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def countSubstrings(self, s: str) -> int:
count = 0
for i in range(len(s)):
# odd
j = i
k = i
while j >= 0 and k < len(s) and s[j] == s[k]:
count += 1
j -= 1
k += 1
# even
j = i
k = i + 1
while j >= 0 and k < len(s) and s[j] == s[k]:
count += 1
j -= 1
k += 1
return count
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. Tags: String
Try It!
Discussion
Video
Solution
import collections
class Solution:
def longestPalindrome(self, s: str) -> int:
counter = collections.Counter(s)
longest = 0
has_odd = False
for c in counter:
count = counter[c]
if count % 2 == 0:
longest += count
else:
longest += count - 1
has_odd = True
if has_odd:
longest += 1
return longest
String to Integer (atoi)
Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def myAtoi(self, s: str) -> int:
MIN = -2 ** 31
MAX = 2 ** 31 - 1
i = 0
num = 0
sign = 1
while i < len(s) and s[i] == ' ':
i += 1
if i < len(s) and s[i] == '+':
i += 1
elif i < len(s) and s[i] == '-':
sign = -1
i += 1
while i < len(s) and str.isdigit(s[i]):
num = 10 * num + int(s[i])
i += 1
ans = sign * num
if ans < MIN:
return MIN
elif ans > MAX:
return MAX
else:
return ans
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. Tags: String
Try It!
Discussion
Video
Solution
import collections
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
p_counter = collections.Counter(p)
window_counter = collections.Counter()
start_idx = 0
ans = []
for i in range(len(s)):
c_end = s[i]
window_counter[c_end] += 1
# first true case window is [0, len(p) - 1]
if i >= len(p) - 1:
if p_counter == window_counter:
ans.append(start_idx)
c_start = s[start_idx]
if c_start in window_counter:
window_counter[c_start] -= 1
if window_counter[c_start] == 0:
del window_counter[c_start]
start_idx += 1
return ans
Array
Two Sum
Given an array of integers, return indices of the two numbers such that they add up to a specific target. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
target_dif = {}
for i in range(len(nums)):
num = nums[i]
if num in target_dif:
return [target_dif[num], i]
else:
dif = target - num
target_dif[dif] = i
Contains Duplicate
Given an array of integers, find if the array contains any duplicates. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
num_exists = set()
for num in nums:
if num in num_exists:
return True
else:
num_exists.add(num)
return False
Product of Array Except Self
Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i]. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
ans = [1 for i in range(len(nums))]
p = 1
for i in range(len(nums)):
ans[i] *= p
p *= nums[i]
p = 1
for i in range(len(nums) - 1, -1, -1):
ans[i] *= p
p *= nums[i]
return ans
Maximum Product Subarray
Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def maxProduct(self, nums: List[int]) -> int:
max_prod = nums[0]
prev_max = nums[0]
prev_min = nums[0]
for num in nums[1:]:
cur_max = max(num, num * prev_max, num * prev_min)
cur_min = min(num, num * prev_max, num * prev_min)
max_prod = max(max_prod, cur_max)
prev_max = cur_max
prev_min = cur_min
return max_prod
Find Minimum in Rotated Sorted Array
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. Find the minimum element. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def findMin(self, nums: List[int]) -> int:
lo = 0
hi = len(nums) - 1
while lo < hi:
mid = lo + (hi - lo) // 2
# important to do mid, hi comparison so we converge down to min instead of highest lo num
if nums[mid] < nums[hi]:
hi = mid
else:
lo = mid + 1
return nums[lo]
Search in Rotated Sorted Array
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. You are given a target value to search. If found in the array return its index, otherwise return -1. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def search(self, nums: List[int], target: int) -> int:
lo = 0
hi = len(nums) - 1
while lo <= hi:
mid = lo + (hi - lo) // 2
if target == nums[mid]:
return mid
if nums[lo] <= nums[mid]:
if nums[lo] <= target <= nums[mid]:
hi = mid - 1
else:
lo = mid + 1
else:
if nums[mid] <= target <= nums[hi]:
lo = mid + 1
else:
hi = mid - 1
return -1
3Sum
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
ans = []
for i in range(len(nums) - 2):
if i == 0 or nums[i] != nums[i - 1]:
self.two_sum(nums, i, ans)
return ans
def two_sum(self, nums, i, ans):
target = -nums[i]
j = i + 1
k = len(nums) - 1
while j < k:
if nums[j] + nums[k] < target:
j += 1
elif nums[j] + nums[k] > target:
k -= 1
else:
ans.append([nums[i], nums[j], nums[k]])
while j < k and nums[j] == nums[j + 1]:
j += 1
while j < k and nums[k] == nums[k - 1]:
k -= 1
j += 1
k -= 1
Container With Most Water
Given n non-negative integers a_1, a_2, ..., a_n , where each represents a point at coordinate (i, a_i). n vertical lines are drawn such that the two endpoints of line i is at (i, a_i) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def maxArea(self, height: List[int]) -> int:
lo = 0
hi = len(height) - 1
max_area = 0
while lo < hi:
if height[lo] < height[hi]:
area = height[lo] * (hi - lo)
if area > max_area:
max_area = area
lo += 1
else:
area = height[hi] * (hi - lo)
if area > max_area:
max_area = area
hi -= 1
return max_area
Majority Element
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. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def majorityElement(self, nums: List[int]) -> int:
count = 0
majority_elem = None
for num in nums:
if count == 0:
majority_elem = num
if majority_elem == num:
count += 1
else:
count -= 1
return majority_elem
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. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def sortColors(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
red = 0
white = 0
blue = len(nums) - 1
while white <= blue:
if nums[white] == 0:
tmp = nums[red]
nums[red] = nums[white]
nums[white] = tmp
red += 1
white += 1
elif nums[white] == 1:
white += 1
else:
tmp = nums[blue]
nums[blue] = nums[white]
nums[white] = tmp
blue -= 1
Trapping Rain Water
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining. Tags: Stack
Try It!
Discussion
Video
Solution
class Solution:
def trap(self, height: List[int]) -> int:
volume = 0
left = 0
right = len(height) - 1
l_max = 0
r_max = 0
while left < right:
l_max = max(height[left], l_max)
r_max = max(height[right], r_max)
if l_max <= r_max:
volume += l_max - height[left]
left += 1
else:
volume += r_max - height[right]
right -= 1
return volume
Dynamic Programming
Climbing Stairs
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def climbStairs(self, n: int) -> int:
dp = [0 for i in range(n + 1)]
dp[0] = 1
dp[1] = 1
for i in range(2, n + 1):
dp[i] += dp[i - 1] + dp[i - 2]
return dp[n]
Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
dp = [1 for i in range(len(nums))]
max_val = 1
for i in range(len(nums)):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j] + 1)
max_val = max(dp[i], max_val)
return max_val
Longest Common Subsequence
Given two strings text1 and text2, return the length of their longest common subsequence. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
dp = [[0 for j in range(len(text2) + 1)] for i in range(len(text1) + 1)]
for i in range(1, len(text1) + 1):
for j in range(1, len(text2) + 1):
if text1[i - 1] == text2[j - 1]:
dp[i][j] = dp[i - 1][j - 1] + 1
else:
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
return dp[len(text1)][len(text2)]
Word Break Problem
Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
dp = [False for i in range(len(s) + 1)]
dp[0] = True
for c in range(len(s) + 1):
for word in wordDict:
if c >= len(word):
if dp[c - len(word)] and s[c - len(word):c] == word:
dp[c] = True
return dp[-1]
Combination Sum IV
Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def combinationSum4(self, nums: List[int], target: int) -> int:
dp = [0 for i in range(target + 1)]
dp[0] = 1
for i in range(1, target + 1):
for j in range(len(nums)):
num = nums[j]
if num <= i:
dp[i] += dp[i - num]
return dp[target]
House Robber
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
if len(nums) == 1:
return nums[0]
dp = [0 for i in range(len(nums))]
dp[0] = nums[0]
dp[1] = max(nums[0], nums[1])
for i in range(2, len(nums)):
dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])
return dp[len(nums) - 1]
House Robber II
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night. Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def rob(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
if len(nums) == 1:
return nums[0]
dp_normal = [0 for i in range(len(nums))]
dp_round = [0 for i in range(len(nums))]
dp_normal[0] = nums[0]
dp_normal[1] = max(nums[0], nums[1])
dp_round[1] = nums[1]
for i in range(2, len(nums)):
dp_normal[i] = max(dp_normal[i - 1], dp_normal[i - 2] + nums[i])
dp_round[i] = max(dp_round[i - 1], dp_round[i - 2] + nums[i])
return max(dp_normal[len(nums) - 2], dp_round[len(nums) - 1])
Unique Paths
A robot is located at the top-left corner of a m x n grid. The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid. How many possible unique paths are there? Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [[0 for c in range(n)] for r in range(m)]
for r in range(m):
dp[r][0] = 1
for c in range(n):
dp[0][c] = 1
for r in range(1, m):
for c in range(1, n):
dp[r][c] += dp[r - 1][c] + dp[r][c - 1]
return dp[m - 1][n - 1]
Jump Game
Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def canJump(self, nums: List[int]) -> bool:
reachable = 0
for i in range(len(nums)):
if i > reachable:
return False
reachable = max(reachable, i + nums[i])
return True
01 Matrix
Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
dp = [[float('inf') for j in range(len(mat[0]))] for i in range(len(mat))]
for i in range(len(mat)):
for j in range(len(mat[0])):
if mat[i][j] == 0:
dp[i][j] = 0
if i > 0:
dp[i][j] = min(dp[i][j], 1 + dp[i - 1][j])
if j > 0:
dp[i][j] = min(dp[i][j], 1 + dp[i][j - 1])
for i in range(len(mat) - 1, -1, -1):
for j in range(len(mat[0]) - 1, -1, -1):
if i <= len(mat) - 2:
dp[i][j] = min(dp[i][j], 1 + dp[i + 1][j])
if j <= len(mat[0]) - 2:
dp[i][j] = min(dp[i][j], 1 + dp[i][j + 1])
return dp
Partition Equal Subset Sum
Given an integer array nums, return true if you can partition the array into two subsets such that the sum of the elements in both subsets is equal or false otherwise. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def canPartition(self, nums: List[int]) -> bool:
tot = sum(nums)
if tot % 2 != 0:
return False
half = tot // 2
dp = [False for i in range(half + 1)]
dp[0] = True
for num in nums:
for i in range(half, -1 , -1):
if num <= i and dp[i - num]:
dp[i] = True
return dp[-1]
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. Tags: Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
dp = [[] for i in range(target + 1)]
for c in candidates:
for i in range(c, target + 1):
if c == i:
dp[i].append([c])
for subcandidate in dp[i - c]:
dp[i].append([c] + subcandidate)
return dp[-1]
Interval
Insert Interval
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). You may assume that the intervals were initially sorted according to their start times. Tags: Interval
Try It!
Discussion
Video
Solution
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
left = []
right = []
for cur in intervals:
if cur[1] < newInterval[0]:
left.append(cur)
elif cur[0] > newInterval[1]:
right.append(cur)
else:
newInterval[0] = min(newInterval[0], cur[0])
newInterval[1] = max(newInterval[1], cur[1])
return left + [newInterval] + right
Graph
Clone Graph
Given a reference of a node in a connected undirected graph. Return a deep copy (clone) of the graph. Tags: Graph
Try It!
Discussion
Video
Solution
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""
from collections import deque
class Solution:
def cloneGraph(self, node: 'Node') -> 'Node':
if not node:
return None
# Dictionary to store the mapping of original nodes to cloned nodes
clones = {}
# Create a clone of the starting node
clones[node] = Node(node.val)
# Queue for BFS traversal
queue = deque([node])
while queue:
curr = queue.popleft()
# Iterate over the neighbors of the current node
for neighbor in curr.neighbors:
if neighbor not in clones:
# Create a clone of the neighbor if it doesn't exist
clones[neighbor] = Node(neighbor.val)
queue.append(neighbor)
# Add the cloned neighbor to the cloned node's neighbors list
clones[curr].neighbors.append(clones[neighbor])
return clones[node]
Course Schedule
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses? Tags: Graph
Try It!
Discussion
Video
Solution
import collections
class Solution:
def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
graph = collections.defaultdict(set)
for x, y in prerequisites:
graph[x].add(y)
visited = [0 for i in range(numCourses)]
for node in range(numCourses):
if not self.dfs(node, graph, visited):
return False
return True
def dfs(self, node, graph, visited):
if visited[node] == -1:
return False
if visited[node] == 1:
return True
visited[node] = -1
for subnode in graph[node]:
if not self.dfs(subnode, graph, visited):
return False
visited[node] = 1
return True
Pacific Atlantic Water Flow
Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the "Pacific ocean" touches the left and top edges of the matrix and the "Atlantic ocean" touches the right and bottom edges. Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower. Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean. Tags: Graph
Try It!
Discussion
Video
Solution
class Solution:
def pacificAtlantic(self, matrix: List[List[int]]) -> List[List[int]]:
if not matrix:
return []
m = len(matrix)
n = len(matrix[0])
p_visited = [[False for c in range(n)] for r in range(m)]
a_visited = [[False for c in range(n)] for r in range(m)]
res = []
for r in range(m):
self.dfs(matrix, r, 0, p_visited, m, n)
self.dfs(matrix, r, n - 1, a_visited, m, n)
for c in range(n):
self.dfs(matrix, 0, c, p_visited, m, n)
self.dfs(matrix, m - 1, c, a_visited, m, n)
for r in range(m):
for c in range(n):
if p_visited[r][c] and a_visited[r][c]:
res.append([r, c])
return res
def dfs(self, matrix, r, c, visited, m, n):
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
visited[r][c] = True
for direction in directions:
next_r = r + direction[0]
next_c = c + direction[1]
if next_r < 0 or next_r >= m:
continue
if next_c < 0 or next_c >= n:
continue
if visited[next_r][next_c]:
continue
if matrix[next_r][next_c] < matrix[r][c]:
continue
self.dfs(matrix, next_r, next_c, visited, m, n)
Flood Fill
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. Return the modified image after performing the flood fill. Tags: Graph
Try It!
Discussion
Video
Solution
class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
visited = [[False for j in range(len(image[0]))] for i in range(len(image))]
prev_color = image[sr][sc]
self.dfs(image, visited, sr, sc, prev_color, color)
return image
def dfs(self, image, visited, i, j, prev_color, color):
if i < 0 or i >= len(image):
return
if j < 0 or j >= len(image[0]):
return
if image[i][j] != prev_color or visited[i][j]:
return
visited[i][j] = True
image[i][j] = color
self.dfs(image, visited, i + 1, j, prev_color, color)
self.dfs(image, visited, i - 1, j, prev_color, color)
self.dfs(image, visited, i, j + 1, prev_color, color)
self.dfs(image, visited, i, j - 1, prev_color, color)
Rotting Oranges
Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1. Tags: Graph
Try It!
Discussion
Video
Solution
import collections
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
queue = collections.deque()
to_visit = set()
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 2:
queue.appendleft((i, j))
if grid[i][j] == 1:
to_visit.add((i, j))
num_min = 0
while queue and to_visit:
for _ in range(len(queue)):
i, j = queue.pop()
for coords in [(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)]:
if coords in to_visit:
to_visit.remove(coords)
queue.appendleft(coords)
num_min += 1
if to_visit:
return -1
return num_min
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. 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. Tags: Graph
Try It!
Discussion
Video
Solution
from collections import defaultdict
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
graph = defaultdict(set)
email_to_name = {}
for acc in accounts:
name = acc[0]
first_email = acc[1]
for email in acc[1:]:
graph[email].add(first_email)
graph[first_email].add(email)
email_to_name[email] = name
visited = set()
ans = []
for email in graph:
if email not in visited:
related_emails = []
self.dfs(email, graph, visited, related_emails)
name = email_to_name[email]
ans.append([name] + sorted(related_emails))
return ans
def dfs(self, email, graph, visited, related_emails):
visited.add(email)
related_emails.append(email)
for nei in graph[email]:
if nei not in visited:
self.dfs(nei, graph, visited, related_emails)
Minimum Height Trees
Given a tree of n nodes, return a list of all MHTs' root labels. Tags: Graph
Try It!
Discussion
Video
Solution
import collections
class Solution:
def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
if n == 1:
return [0]
tree = collections.defaultdict(set)
for x, y in edges:
tree[x].add(y)
tree[y].add(x)
# only connected to 1 node
leaves = [i for i in range(n) if len(tree[i]) == 1]
while n > 2:
n -= len(leaves)
new_leaves = []
for i in leaves:
# tree[i] will only have 1 elem
j = tree[i].pop()
tree[j].remove(i)
if len(tree[j]) == 1:
new_leaves.append(j)
leaves = new_leaves
return leaves
Word Ladder
Given two words, beginWord and endWord, and a dictionary wordList, return the number of words in the shortest transformation sequence from beginWord to endWord, or 0 if no such sequence exists. Tags: Graph
Try It!
Discussion
Video
Solution
import collections
import string
class Solution:
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
word_set = set(wordList)
queue = collections.deque()
queue.appendleft((beginWord, 1))
while queue:
word, length = queue.pop()
if word == endWord:
return length
for i in range(len(word)):
for c in string.ascii_lowercase:
new_word = word[:i] + c + word[i + 1:]
if new_word in word_set:
word_set.remove(new_word)
queue.appendleft((new_word, length + 1))
return 0
Matrix
Set Matrix Zeroes
Given an m x n matrix. If an element is 0, set its entire row and column to 0. Do it in-place. Tags: Matrix
Try It!
Discussion
Video
Solution
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
top_has_zero = False
for j in range(len(matrix[0])):
if matrix[0][j] == 0:
top_has_zero = True
break
# Create a marker using first row and column
# 010
# 110
# 001
for i in range(1, len(matrix)):
for j in range(len(matrix[0])):
if matrix[i][j] == 0:
matrix[i][0] = 0
matrix[0][j] = 0
# Set the zeros, backwards iterating through the row
for i in range(1, len(matrix)):
for j in range(len(matrix[0]) - 1, -1, -1):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
if top_has_zero:
for j in range(len(matrix[0])):
matrix[0][j] = 0
Spiral Matrix
Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. Tags: Matrix
Try It!
Discussion
Video
Solution
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
res = []
row_lo = 0
row_hi = len(matrix) - 1
col_lo = 0
col_hi = len(matrix[0]) - 1
while row_lo <= row_hi and col_lo <= col_hi:
for c in range(col_lo, col_hi + 1):
res.append(matrix[row_lo][c])
row_lo += 1
for r in range(row_lo, row_hi + 1):
res.append(matrix[r][col_hi])
col_hi -= 1
if row_lo <= row_hi:
for c in range(col_hi, col_lo - 1, -1):
res.append(matrix[row_hi][c])
row_hi -= 1
if col_lo <= col_hi:
for r in range(row_hi, row_lo - 1, -1):
res.append(matrix[r][col_lo])
col_lo += 1
return res
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, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. Tags: Matrix
Try It!
Discussion
Video
Alternative Solution
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
l = 0
r = len(matrix) - 1
while l < r:
for i in range(r - l):
top = l
bottom = r
# save the topleft
top_left = matrix[top][l + i]
# move bottom left into top left
matrix[top][l + i] = matrix[bottom - i][l]
# move bottom right into bottom left
matrix[bottom - i][l] = matrix[bottom][r - i]
# move top right into bottom right
matrix[bottom][r - i] = matrix[top + i][r]
# move top left into top right
matrix[top + i][r] = top_left
r -= 1
l += 1
Word Search
Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. Tags: Matrix
Try It!
Discussion
Video
Solution
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
if word == '':
return False
visited = [[False for j in range(len(board[0]))] for i in range(len(board))]
for i in range(len(board)):
for j in range(len(board[0])):
if self.dfs(board, i, j, visited, word):
return True
return False
def dfs(self, board, i, j, visited, word):
if word == '':
return True
if i < 0 or i >= len(board):
return False
if j < 0 or j >= len(board[0]):
return False
if visited[i][j]:
return False
if word[0] != board[i][j]:
return False
visited[i][j] = True
hasWord = self.dfs(board, i - 1, j, visited, word[1:]) \
or self.dfs(board, i + 1, j, visited, word[1:]) \
or self.dfs(board, i, j - 1, visited, word[1:]) \
or self.dfs(board, i, j + 1, visited, word[1:])
visited[i][j] = False
return hasWord
Tree
Maximum Depth of Binary Tree
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: TreeNode) -> int:
if not root:
return 0
left_depth = self.maxDepth(root.left)
right_depth = self.maxDepth(root.right)
return 1 + max(left_depth, right_depth)
Same Tree
Given two binary trees, write a function to check if they are the same or not. Two binary trees are considered the same if they are structurally identical and the nodes have the same value. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
if p == None and q == None:
return True
if p == None:
return False
if q == None:
return False
return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
Invert/Flip Binary Tree
Invert a binary tree. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
if not root:
return
tmp_left = self.invertTree(root.right)
tmp_right = self.invertTree(root.left)
root.left = tmp_left
root.right = tmp_right
return root
Binary Tree Maximum Path Sum
Given a non-empty binary tree, find the maximum path sum. For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxPathSum(self, root: TreeNode) -> int:
self.res = float('-inf')
self.helper(root)
return self.res
def helper(self, root):
if not root:
return 0
left = self.helper(root.left)
right = self.helper(root.right)
if root.val + left + right > self.res:
self.res = root.val + left + right
pos_max_path = root.val + max(left, right)
if pos_max_path > 0:
return pos_max_path
else:
return 0
Binary Tree Level Order Traversal
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). Tags: Tree
Try It!
Discussion
Video
Solution
import collections
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
queue = collections.deque()
queue.appendleft((root, 0))
res = []
while queue:
top, level = queue.pop()
if len(res) == level:
res.append([])
res[level].append(top.val)
if top.left:
queue.appendleft((top.left, level + 1))
if top.right:
queue.appendleft((top.right, level + 1))
return res
Serialize and Deserialize Binary Tree
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
if not root:
return 'n'
val = str(root.val)
left = self.serialize(root.left)
right = self.serialize(root.right)
return val + ',' + left + ',' + right
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
self.data = data
if self.data[0] == 'n':
return None
first_break = self.data.find(',')
node = TreeNode(int(self.data[:first_break]))
node.left = self.deserialize(self.data[first_break + 1:])
second_break = self.data.find(',')
node.right = self.deserialize(self.data[second_break + 1:])
return node
# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))
Subtree of Another Tree
Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node's descendants. The tree s could also be considered as a subtree of itself. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSubtree(self, s: TreeNode, t: TreeNode) -> bool:
if s == None or t == None:
return False
elif self.compare(s, t):
return True
else:
return self.isSubtree(s.left, t) or self.isSubtree(s.right, t)
def compare(self, s, t):
if s == None and t == None:
return True
elif s == None or t == None:
return False
elif s.val == t.val:
return self.compare(s.left, t.left) and self.compare(s.right, t.right)
else:
return False
Validate Binary Search Tree
Given a binary tree, determine if it is a valid binary search tree (BST). Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
return self.helper(root, float('-inf'), float('inf'))
def helper(self, root, lower, upper):
if root is None:
return True
elif root.val >= upper:
return False
elif root.val <= lower:
return False
else:
return self.helper(root.left, lower, root.val) and self.helper(root.right, root.val, upper)
Kth Smallest Element in a BST
Given a binary search tree, write a function kth Smallest to find the kth smallest element in it. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def kthSmallest(self, root: TreeNode, k: int) -> int:
lst = []
self.helper(root, lst)
return lst[k - 1]
def helper(self, root, lst):
# perform an inorder traversal
if not root:
return
self.helper(root.left, lst)
lst.append(root.val)
self.helper(root.right, lst)
Lowest Common Ancestor of a Binary Search Tree
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. Tags: Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if p.val < root.val and q.val < root.val:
return self.lowestCommonAncestor(root.left, p, q)
elif p.val > root.val and q.val > root.val:
return self.lowestCommonAncestor(root.right, p, q)
else:
return root
Implement Trie (Prefix Tree)
Implement a trie with insert, search, and startsWith methods. Tags: Tree
Try It!
Discussion
Video
Solution
class Trie:
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = {}
def insert(self, word: str) -> None:
"""
Inserts a word into the trie.
"""
trie = self.root
for c in word:
if c not in trie:
trie[c] = {}
trie = trie[c]
trie['#'] = '#'
def search(self, word: str) -> bool:
"""
Returns if the word is in the trie.
"""
trie = self.root
for c in word:
if c not in trie:
return False
trie = trie[c]
return '#' in trie
def startsWith(self, prefix: str) -> bool:
"""
Returns if there is any word in the trie that starts with the given prefix.
"""
trie = self.root
for c in prefix:
if c not in trie:
return False
trie = trie[c]
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
Add and Search Word
Design a data structure that supports adding new words and finding if a string matches any previously added string. Tags: Tree
Try It!
Discussion
Video
Solution
class WordDictionary:
def __init__(self):
"""
Initialize your data structure here.
"""
self.trie = {}
def addWord(self, word: str) -> None:
level = self.trie
for c in word:
if c not in level:
level[c] = {}
level = level[c]
level['#'] = '#'
def search(self, word: str) -> bool:
return self.helper(word, self.trie)
def helper(self, word, level):
if word == '':
return '#' in level
c = word[0]
if c == '.':
for pos_c in level:
if pos_c != '#' and self.helper(word[1:], level[pos_c]):
return True
return False
elif c not in level:
return False
else:
return self.helper(word[1:], level[c])
# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)
Binary Tree
Diameter of Binary Tree
Given the root of a binary tree, return the length of the diameter of the tree. Tags: Binary Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
self.max_diameter = 0
self.helper(root)
return self.max_diameter
def helper(self, root):
if not root:
return 0
left = self.helper(root.left)
right = self.helper(root.right)
if left + right > self.max_diameter:
self.max_diameter = left + right
return 1 + max(left, right)
Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. Tags: Binary Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root:
return root
if root == p or root == q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if left and right:
return root
elif left:
return left
elif right:
return right
else:
return None
Binary Tree Right Side View
Given the root of a binary tree, return the length of the diameter of the tree. Tags: Binary Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
view = []
self.helper(root, view, 0)
return view
def helper(self, root, view, level):
if not root:
return
if level == len(view):
view.append(root.val)
self.helper(root.right, view, level + 1)
self.helper(root.left, view, level + 1)
Binary Search
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. Tags: Binary Search
Try It!
Discussion
Video
Solution
class Solution:
def search(self, nums: List[int], target: int) -> int:
lo = 0
hi = len(nums) - 1
while lo <= hi:
mid = (lo + hi) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1
First Bad Version
You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad. 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. Tags: Binary Search
Try It!
Discussion
Video
Solution
# The isBadVersion API is already defined for you.
# def isBadVersion(version: int) -> bool:
class Solution:
def firstBadVersion(self, n: int) -> int:
lo = 0
hi = n
while lo <= hi:
mid = (lo + hi) // 2
if isBadVersion(mid):
hi = mid - 1
else:
lo = mid + 1
return lo
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. Tags: Binary Search
Try It!
Discussion
Video
Solution
import collections
class TimeMap:
def __init__(self):
self.store = collections.defaultdict(list)
def set(self, key: str, value: str, timestamp: int) -> None:
self.store[key].append([value, timestamp])
def get(self, key: str, timestamp: int) -> str:
if key not in self.store:
return ''
ans = ''
values = self.store[key]
lo = 0
hi = len(values) - 1
while lo <= hi:
mid = (lo + hi) // 2
if values[mid][1] <= timestamp:
ans = values[mid][0]
lo = mid + 1
else:
hi = mid - 1
return ans
# Your TimeMap object will be instantiated and called as such:
# obj = TimeMap()
# obj.set(key,value,timestamp)
# param_2 = obj.get(key,timestamp)
Maximum Profit in Job Scheduling
We have n jobs, where every job is scheduled to be done from startTime[i] to endTime[i], obtaining a profit of profit[i]. You're given the startTime, endTime and profit arrays, return the maximum profit you can take such that there are no two jobs in the subset with overlapping time range. Tags: Binary Search, Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
jobs = sorted(zip(startTime, endTime, profit), key=lambda x: x[1])
# end, curr_profit
dp = [(0, 0)]
for start, end, profit in jobs:
idx = self.binary_search(dp, start)
last_profit = dp[-1][1]
curr_profit = dp[idx - 1][1] + profit
if curr_profit > last_profit:
dp.append((end, curr_profit))
return dp[-1][1]
def binary_search(self, dp, target):
lo = 0
hi = len(dp) - 1
while lo <= hi:
mid = (lo + hi) // 2
if dp[mid][0] <= target:
lo = mid + 1
else:
hi = mid - 1
return lo
Binary Search Tree
Balanced Binary Search
Given a binary tree, determine if it is height-balanced. Tags: Binary Search Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
return self.helper(root)[0]
def helper(self, root):
if not root:
return [True, 0]
left = self.helper(root.left)
right = self.helper(root.right)
balanced = left[0] and right[0] and abs(left[1] - right[1]) <= 1
depth = 1 + max(left[1], right[1])
return [balanced, depth]
Recursion
Permutations
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order. Tags: Search, Backtracking
Try It!
Discussion
Video
Solution
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
path = []
self.dfs(nums, path, res)
return res
def dfs(self, nums, path, res):
if nums == []:
res.append(path)
return
# perform backtracking
for i in range(len(nums)):
self.dfs(nums[:i] + nums[i + 1:], path + [nums[i]], res)
Subsets
Given an integer array nums of unique elements, return all possible subsets (the power set). Tags: Search, Backtracking
Try It!
Discussion
Video
Solution
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
path = []
self.dfs(nums, path, res)
return res
def dfs(self, nums, path, res):
res.append(path)
# perform backtracking
for i in range(len(nums)):
self.dfs(nums[:i], path + [nums[i]], res)
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. Tags: Recursion
Try It!
Discussion
Video
Solution
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
mapping = {
'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz'
}
if not digits:
return []
ans = []
self.dfs(digits, '', ans, mapping)
return ans
def dfs(self, digits, path, ans, mapping):
if not digits:
ans.append(path)
return
d = digits[0]
characters = mapping[d]
for c in characters:
self.dfs(digits[1:], path + c, ans, mapping)
Linked List
Reverse Linked List
Reverse a singly linked list. Tags: Linked List
Try It!
Discussion
Video
Solution
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
first = head
second = None
while first:
temp = first.next
first.next = second
second = first
first = temp
return second
Detect Cycle in a Linked List
Given head, the head of a linked list, determine if the linked list has a cycle in it. Tags: Linked List
Try It!
Discussion
Video
Solution
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
fast = head
slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast == slow:
return True
return False
Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new sorted list. The new list should be made by splicing together the nodes of the first two lists. Tags: Linked List
Try It!
Discussion
Video
Solution
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
dummy = ListNode("dummy")
cur = dummy
while l1 and l2:
if l1.val < l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
if l1:
cur.next = l1
if l2:
cur.next = l2
return dummy.next
Remove Nth Node From End Of List
Given a linked list, remove the n-th node from the end of list and return its head. Tags: Linked List
Try It!
Discussion
Video
Solution
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
dummy = ListNode('dummy')
dummy.next = head
first = dummy
for i in range(n + 1):
first = first.next
second = dummy
while first:
first = first.next
second = second.next
second.next = second.next.next
return dummy.next
Reorder List
Given a singly linked list L: L0->L1->...->Ln-1->Ln, reorder it to: L0->Ln->L1->Ln-1->L2->Ln-2->... Tags: Linked List
Try It!
Discussion
Video
Solution
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if not head:
return
fast = head.next
slow = head
# ensure the first part has the same or one more node
while fast and fast.next:
fast = fast.next.next
slow = slow.next
# reverse the second half
cur = slow.next
slow.next = None
prev = None
while cur:
tmp = cur.next
cur.next = prev
prev = cur
cur = tmp
# combine first part and second part
first = head
second = prev
while second:
tmp = second.next
second.next = first.next
first.next = second
first = first.next.next
second = tmp
Middle of the Linked List
Given the head of a singly linked list, return the middle node of the linked list. Tags: Linked List
Try It!
Discussion
Video
Solution
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
fast = head
slow = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
return slow
LRU Cache
Design a data structure that follows the constraints of a Least Recently Used (LRU) cache. Tags: Linked List
Try It!
Discussion
Video
Solution
class Node:
def __init__(self, key=None, value=None):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = {}
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.prev = self.head
def get(self, key: int) -> int:
if key in self.cache:
node = self.cache[key]
self._remove(node)
self._add(node)
return node.value
return -1
def put(self, key: int, value: int) -> None:
if key in self.cache:
self._remove(self.cache[key])
node = Node(key, value)
self._add(node)
self.cache[key] = node
if len(self.cache) > self.capacity:
lru_node = self.head.next
self._remove(lru_node)
del self.cache[lru_node.key]
def _remove(self, node):
node.prev.next = node.next
node.next.prev = node.prev
def _add(self, node):
node.prev = self.tail.prev
node.next = self.tail
self.tail.prev.next = node
self.tail.prev = node
Hash Table
Ransom Note
Given two strings ransomNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise. Each letter in magazine can only be used once in ransomNote. Tags: Hash Table
Try It!
Discussion
Video
Solution
import collections
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
ransom_counter = collections.Counter(ransomNote)
for c in magazine:
if c in ransom_counter:
ransom_counter[c] -= 1
for c in ransom_counter:
if ransom_counter[c] > 0:
return False
return True
Stack
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). Tags: Stack
Try It!
Discussion
Video
Solution
class MyQueue:
def __init__(self):
self.stack = []
self.stack_tmp = []
def push(self, x: int) -> None:
self.stack.append(x)
def pop(self) -> int:
first = None
while self.stack:
if len(self.stack) == 1:
first = self.stack.pop()
else:
self.stack_tmp.append(self.stack.pop())
while self.stack_tmp:
self.stack.append(self.stack_tmp.pop())
return first
def peek(self) -> int:
first = None
while self.stack:
if len(self.stack) == 1:
first = self.stack.pop()
self.stack_tmp.append(first)
else:
self.stack_tmp.append(self.stack.pop())
while self.stack_tmp:
self.stack.append(self.stack_tmp.pop())
return first
def empty(self) -> bool:
return not self.stack
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
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. Tags: Stack
Try It!
Discussion
Video
Solution
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for c in tokens:
if c not in '+-/*':
stack.append(int(c))
else:
b = stack.pop()
a = stack.pop()
if c == '+':
stack.append(a + b)
elif c == '-':
stack.append(a - b)
elif c == '*':
stack.append(a * b)
else:
stack.append(int(a / b))
return stack.pop()
Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. Tags: Stack
Try It!
Discussion
Video
Solution
class MinStack:
def __init__(self):
self.stack = []
def push(self, val: int) -> None:
if not self.stack:
self.stack.append((val, val))
else:
min_elem = min(val, self.stack[-1][1])
self.stack.append((val, min_elem))
def pop(self) -> None:
if self.stack:
self.stack.pop()
def top(self) -> int:
if self.stack:
return self.stack[-1][0]
def getMin(self) -> int:
if self.stack:
return self.stack[-1][1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
Basic Calculator
Given a string s representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation. Tags: Stack
Try It!
Discussion
Video
Solution
class Solution:
def calculate(self, s: str) -> int:
stack = []
sign = 1
num = 0
for c in s:
if str.isdigit(c):
num = 10 * num + int(c)
elif c in '+-':
stack.append(sign * num)
num = 0
if c == '+':
sign = 1
elif c == '-':
sign = -1
elif c == '(':
stack.append(sign)
stack.append(c)
sign = 1
elif c == ')':
tmp = sign * num
while stack[-1] != '(':
tmp += stack.pop()
stack.pop() # '('
prev_sign = stack.pop()
stack.append(prev_sign * tmp)
num = 0
sign = 1
return sum(stack) + sign * num
Largest Rectangle in Histogram
Given an array of integers heights representing the histogram's bar height where the width of each bar is 1, return the area of the largest rectangle in the histogram. Tags: Stack
Try It!
Discussion
Video
Solution
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
stack = []
max_area = 0
for i in range(len(heights)):
h = heights[i]
start = i
while stack and stack[-1][1] > h:
idx, old_h = stack.pop()
start = idx
area = old_h * (i - start)
max_area = max(max_area, area)
stack.append((start, h))
for i, h in stack:
area = h * (len(heights) - i)
max_area = max(max_area, area)
return max_area
Heap
Merge K Sorted Lists
You are given an array of k linked-lists lists, each linked-list is sorted in ascending order. Tags: Heap, Linked List
Try It!
Discussion
Video
Solution
Simple solution creating new nodes
import heapq
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
min_heap = []
for node in lists:
while node != None:
heapq.heappush(min_heap, node.val)
node = node.next
dummy = ListNode("dummy")
cur = dummy
while min_heap:
min_val = heapq.heappop(min_heap)
cur.next = ListNode(min_val)
cur = cur.next
return dummy.next
Reuse nodes fix comparison with Monkey Patching and remove cycles
import heapq
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
ListNode.__lt__ = lambda self, other: self.val < other.val
max_heap = []
for node in lists:
while node:
heapq.heappush(max_heap, node)
node = node.next
dummy = ListNode()
cur = dummy
while max_heap:
node = heapq.heappop(max_heap)
cur.next = node
cur = cur.next
cur.next = None
return dummy.next
Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements. Tags: Heap
Try It!
Discussion
Video
Solution
import heapq
from collections import Counter
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
counter = Counter(nums)
heap = []
for num in counter:
count = counter[num]
heapq.heappush(heap, (-count, num))
ans = []
for i in range(k):
neg_count, num = heapq.heappop(heap)
ans.append(num)
return ans
Find Median from Data Stream
Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. Tags: Heap
Try It!
Discussion
Video
Solution
import heapq
class MedianFinder:
def __init__(self):
self.lower = []
self.greater = []
def addNum(self, num: int) -> None:
if len(self.lower) == len(self.greater):
heapq.heappush(self.greater, num)
greater_min = heapq.heappop(self.greater)
heapq.heappush(self.lower, -greater_min)
else:
heapq.heappush(self.lower, -num)
lower_max = heapq.heappop(self.lower)
heapq.heappush(self.greater, -lower_max)
def findMedian(self) -> float:
if len(self.lower) == len(self.greater):
return (-self.lower[0] + self.greater[0]) / 2
else:
return -self.lower[0]
# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()
K Closest Points 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). Tags: Heap
Try It!
Discussion
Video
Solution
import heapq
import math
class Solution:
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
min_heap = []
for point in points:
dist = math.sqrt(point[0] ** 2 + point[1] ** 2)
heapq.heappush(min_heap, (dist, point))
ans = []
for i in range(k):
dist, point = heapq.heappop(min_heap)
ans.append(point)
return ans
Binary
Sum of Two Integers
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Tags: Binary
Try It!
Discussion
Video
Solution
class Solution:
def getSum(self, a: int, b: int) -> int:
mask = 0xffffffff
while b & mask != 0:
carry = a & b
a ^= b
b = carry << 1
# if our answer was negative b/carry would keep on being shifted outside of 32 bits
if b == 0:
return a
else:
return a & mask
Number of 1 Bits
Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight). Tags: Binary
Try It!
Discussion
Video
Solution
class Solution:
def hammingWeight(self, n: int) -> int:
count = 0
while n:
if n & 1:
count += 1
n >>= 1
return count
Counting Bits
Given a non negative integer number num. For every numbers i in the range 0 <= i <= num calculate the number of 1's in their binary representation and return them as an array. Tags: Binary, Dynamic Programming
Try It!
Discussion
Video
Solution
class Solution:
def countBits(self, num: int) -> List[int]:
# numbers can be represented as 2n or 2n + 1
# numBits(2n) == numBits(n)
# numBits(2n + 1) == numBit(n) + 1
dp = [0 for i in range(num + 1)]
for i in range(1, num + 1):
dp[i] = dp[i // 2] + (i % 2)
# or with bit operators
# dp[i] = dp[i >> 1] + (i & 1)
return dp
Missing Number
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array. Tags: Binary
Try It!
Discussion
Video
Solution
class Solution:
def missingNumber(self, nums: List[int]) -> int:
res = len(nums)
for i in range(len(nums)):
res = res ^ i ^ nums[i]
return res
Reverse Bits
Reverse bits of a given 32 bits unsigned integer. Tags: Binary
Try It!
Discussion
Video
Solution
class Solution:
def reverseBits(self, n: int) -> int:
res = 0
for i in range(32):
res <<= 1
res |= n & 1
n >>= 1
return res
Add Binary
Given two binary strings a and b, return their sum as a binary string. Tags: Binary
Try It!
Discussion
Video
Solution
class Solution:
def addBinary(self, a: str, b: str) -> str:
carry = 0
result = ''
a = list(a)
b = list(b)
while a or b or carry:
if a:
carry += int(a.pop())
if b:
carry += int(b.pop())
result += str(carry % 2)
carry //= 2
return result[::-1]
Meta
Valid Word Abbreviation
Given a string word and an abbreviation abbr, return whether the string matches the given abbreviation. Tags: String
Try It!
Valid Palindrome II
Given a string s, return true if the s can be palindrome after deleting at most one character from it. Tags: String
Try It!
Discussion
Video
Solution
class Solution:
def validPalindrome(self, s: str) -> bool:
p1 = 0
p2 = len(s) - 1
while p1 < p2:
if s[p1] == s[p2]:
p1 += 1
p2 -= 1
else:
return self.is_palindrome(s, p1 + 1, p2) or self.is_palindrome(s, p1, p2 - 1)
return True
def is_palindrome(self, s: str, p1: int, p2: int) -> bool:
while p1 < p2:
if s[p1] == s[p2]:
p1 += 1
p2 -= 1
else:
return False
return True
This is O(N) becaues the first while checks until a mismatch. Then the second while checks if it can be a palindrome without one of the characters.
Range Sum of BST
Given the root node of a binary search tree and two integers low and high, return the sum of values of all nodes with a value in the inclusive range [low, high]. Tags: Tree
Try It!
Moving Average from Data Stream
Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window. Implement the MovingAverage class. Tags: Queue
Try It!
Diameter of Binary Tree
Given the root of a binary tree, return the length of the diameter of the tree. Tags: Binary Tree
Try It!
Closest Binary Search Tree Value
Given the root of a binary search tree and a target value, return the value in the BST that is closest to the target. If there are multiple answers, print the smallest. Tags: Binary Search Tree
Try It!
Binary Tree Vertical Order Traversal
Given the root of a binary tree, return the vertical order traversal of its nodes' values. (i.e., from top to bottom, column by column). Tags: Binary Tree
Try It!
Minimum Remove to Make Valid Parentheses
Given a string s of '(' , ')' and lowercase English characters.
Your task is to remove the minimum number of parentheses ( '(' or ')', in any positions ) so that the resulting parentheses string is valid and return any valid string. Tags: String, Stack
Try It!
Solution
class Solution:
def minRemoveToMakeValid(self, s: str) -> str:
stack = []
to_remove = set()
for i, c in enumerate(s):
if c == '(':
stack.append(i)
elif c == ')':
if not stack:
to_remove.add(i)
else:
stack.pop()
to_remove.update(stack)
ans = []
for i, c in enumerate(s):
if i not in to_remove:
ans.append(c)
return ''.join(ans)
Follow up, solve this without any additional data structures
class Solution:
def minRemoveToMakeValid(self, s: str) -> str:
# Convert the string to a list for efficient character manipulation
s_list = list(s)
# First pass: remove invalid closing parentheses
open_count = 0
for i in range(len(s_list)):
if s_list[i] == '(':
open_count += 1
elif s_list[i] == ')':
if open_count == 0:
s_list[i] = ''
else:
open_count -= 1
# Second pass: remove invalid opening parentheses
open_count = 0
for i in range(len(s_list) - 1, -1, -1):
if s_list[i] == ')':
open_count += 1
elif s_list[i] == '(':
if open_count == 0:
s_list[i] = ''
else:
open_count -= 1
# Convert the list back to a string and return
return ''.join(s_list)
Lowest Common Ancestor of a Binary Tree III
Given two nodes of a binary tree p and q, return their lowest common ancestor (LCA). Each node will have a reference to its parent node. Tags: Binary Tree
Try It!
Nested List Weight Sum
You are given a nested list of integers nestedList. Each element is either an integer or a list whose elements may also be integers or other lists. The depth of an integer is the number of lists that it is inside of. For example, the nested list [1,[2,2],[[3],2],1] has each integer's value set to its depth. Return the sum of each integer in nestedList multiplied by its depth.
Try It!
Dot Product of Two Sparse Vectors
Try It!
Buildings With an Ocean View
There are n buildings in a line. You are given an integer array heights of size n that represents the heights of the buildings in the line. The ocean is to the right of the buildings. A building has an ocean view if the building can see the ocean without obstructions. Formally, a building has an ocean view if all the buildings to its right have a smaller height. Return a list of indices (0-indexed) of buildings that have an ocean view, sorted in increasing order. Tags: Array
Try It!
Basic Calculator II
Given a string s which represents an expression, evaluate this expression and return its value. Tags: String, Stack
Try It!
Discussion
Video
Solution
class Solution:
def calculate(self, s: str) -> int:
total = 0
operator = '+'
num = 0
past_num = 0
for i, c in enumerate(s):
if c.isdigit():
num = 10 * num + int(c)
if c in '+-*/' or i == len(s) - 1:
if operator == '+':
total += past_num
past_num = num
elif operator == '-':
total += past_num
past_num = -num
elif operator == '*':
past_num *= num
elif operator == '/':
past_num = int(past_num / num)
num = 0
operator = c
return total + past_num
*/
Don't have result +=
because of order of operations.
You have to watch out if c in '+-*/' or i == len(s) - 1:
not elif because c can be a digit and the last number.
Stack solution
class Solution:
def calculate(self, s: str) -> int:
stack = []
num = 0
operator = '+'
for i, c in enumerate(s):
if c.isdigit():
num = 10 * num + int(c)
if c in '+-*/' or i == len(s) - 1:
if operator == '+':
stack.append(num)
elif operator == '-':
stack.append(-num)
elif operator == '*':
stack[-1] *= num
elif operator == '/':
stack[-1] = int(stack[-1] / num)
num = 0
operator = c
return sum(stack)
Random Pick with Weight
You are given a 0-indexed array of positive integers w where w[i] describes the weight of the ith index. You need to implement the function pickIndex(), which randomly picks an index in the range [0, w.length - 1] (inclusive) and returns it. The probability of picking an index i is w[i] / sum(w). Tags: Array, Prefix Sum
Try It!
Kth Largest Element in an Array
Given an integer array nums and an integer k, return the kth largest element in the array. Tags: Sorting, Heap
Try It!
Simplify Path
Given a string path, which is an absolute path (starting with a slash '/') to a file or directory in a Unix-style file system, convert it to the simplified canonical path. Tags: String
Try It!
Convert Binary Search Tree to Sorted Doubly Linked List
Convert a Binary Search Tree to a sorted Circular Doubly-Linked List in place. Tags: Linked List, Binary Search Tree
Try It!
Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. Tags: Binary Tree
Try It!
Discussion
Video
Solution
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root:
return root
if root == p or root == q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
if left and right:
return root
elif left:
return left
elif right:
return right
else:
return None
Minimum Add to Make Parentheses Valid
Return the minimum number of moves required to make s valid. Tags: Stack
Try It!
Pow(x, n)
Implement pow(x, n), which calculates x raised to the power n (i.e., xn). Tags:
Try It!
Sum Root to Leaf Numbers
Return the total sum of all root-to-leaf numbers. Test cases are generated so that the answer will fit in a 32-bit integer. Tags: Tree
Try It!
K Closest Points 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). Tags: Heap
Try It!
Find Peak Element
Given a 0-indexed integer array nums, find a peak element, and return its index. If the array contains multiple peaks, return the index to any of the peaks. Tags: Binary Search
Try It!
Insert into a Sorted Circular Linked List
Try It!
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. Tags: Binary Tree
Try It!
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. Tags: Array
Try It!
Custom Sort String
Permute the characters of s so that they match the order that order was sorted. More specifically, if a character x occurs before a character y in order, then x should occur before y in the permuted string. Tags: String
Try It!
Shortest Path in Binary Matrix
Given an n x n binary matrix grid, return the length of the shortest clear path in the matrix. If there is no clear path, return -1. Tags: BFS, A*
Try It!
Merge Intervals
Try It!
Group Shifted Strings
Given an array of strings strings, group all strings[i] that belong to the same shifting sequence. You may return the answer in any order. Tags: String
Try It!
LRU Cache
Design a data structure that follows the constraints of a Least Recently Used (LRU) cache. Tags: Linked List
Try It!
Discussion
Video
Solution
class Node:
def __init__(self, key=None, value=None):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = {}
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.prev = self.head
def get(self, key: int) -> int:
if key in self.cache:
node = self.cache[key]
self._remove(node)
self._add(node)
return node.value
return -1
def put(self, key: int, value: int) -> None:
if key in self.cache:
self._remove(self.cache[key])
node = Node(key, value)
self._add(node)
self.cache[key] = node
if len(self.cache) > self.capacity:
lru_node = self.head.next
self._remove(lru_node)
del self.cache[lru_node.key]
def _remove(self, node):
node.prev.next = node.next
node.next.prev = node.prev
def _add(self, node):
node.prev = self.tail.prev
node.next = self.tail
self.tail.prev.next = node
self.tail.prev = node
Exclusive Time of Functions
Return the exclusive time of each function in an array, where the value at the ith index represents the exclusive time for the function with ID i. Tags: Array, Stack
Try It!
Maximum Swap
You are given an integer num. You can swap two digits at most once to get the maximum valued number. Return the maximum valued number you can get. Tags:
Try It!
Random Pick Index
Given an integer array nums with possible duplicates, randomly output the index of a given target number. You can assume that the given target number must exist in the array. Tags: Hash Table
Try It!
Copy List with Random Pointer
Try It!
Subarray Sum Equals K
Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k. Tags: Array
Try It!
Diagonal Traverse
Given an m x n matrix mat, return an array of all the elements of the array in a diagonal order. Tags: Array
Try It!
Next Permutation
Given an array of integers nums, find the next permutation of nums. Tags:
Try It!
Top K Frequent Elements
Given a non-empty array of integers, return the k most frequent elements. Tags: Heap
Try It!
Discussion
Video
Solution
import heapq
from collections import Counter
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
counter = Counter(nums)
heap = []
for num in counter:
count = counter[num]
heapq.heappush(heap, (-count, num))
ans = []
for i in range(k):
neg_count, num = heapq.heappop(heap)
ans.append(num)
return ans
3Sum
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. Tags: Array
Try It!
Discussion
Video
Solution
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
ans = []
for i in range(len(nums) - 2):
if i == 0 or nums[i] != nums[i - 1]:
self.two_sum(nums, i, ans)
return ans
def two_sum(self, nums, i, ans):
target = -nums[i]
j = i + 1
k = len(nums) - 1
while j < k:
if nums[j] + nums[k] < target:
j += 1
elif nums[j] + nums[k] > target:
k -= 1
else:
ans.append([nums[i], nums[j], nums[k]])
while j < k and nums[j] == nums[j + 1]:
j += 1
while j < k and nums[k] == nums[k - 1]:
k -= 1
j += 1
k -= 1
Max Consecutive Ones III
Given a binary array nums and an integer k, return the maximum number of consecutive 1's in the array if you can flip at most k 0's. Tags: Array
Try It!
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. Tags: Tree
Try It!
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. 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. Tags: Graph
Try It!
Discussion
Video
Solution
from collections import defaultdict
class Solution:
def accountsMerge(self, accounts: List[List[str]]) -> List[List[str]]:
graph = defaultdict(set)
email_to_name = {}
for acc in accounts:
name = acc[0]
first_email = acc[1]
for email in acc[1:]:
graph[email].add(first_email)
graph[first_email].add(email)
email_to_name[email] = name
visited = set()
ans = []
for email in graph:
if email not in visited:
related_emails = []
self.dfs(email, graph, visited, related_emails)
name = email_to_name[email]
ans.append([name] + sorted(related_emails))
return ans
def dfs(self, email, graph, visited, related_emails):
visited.add(email)
related_emails.append(email)
for nei in graph[email]:
if nei not in visited:
self.dfs(nei, graph, visited, related_emails)
Design Tic-Tac-Toe
Implement the TicTacToe class for the tic-tac-toe game on an n x n board between two players. Tags: Array
Try It!
Product of Two Run-Length Encoded Arrays
Return the product of two run-length encoded arrays. Tags: Array
Try It!
Number of Islands
Given a 2-D Array, count the number of islands in it, where land is connected in the NSEW direction. Tags: Recursion, Search, Union-Find
Try It!
Discussion
Video
Solution
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == '1':
self.dfs_marking(grid, i, j);
count += 1
return count
def dfs_marking(self, grid, i, j):
if i < 0 or i >= len(grid):
return
if j < 0 or j >= len(grid[0]):
return
if grid[i][j] != '1':
return
grid[i][j] = '0'
self.dfs_marking(grid, i + 1, j)
self.dfs_marking(grid, i - 1, j)
self.dfs_marking(grid, i, j + 1)
self.dfs_marking(grid, i, j - 1)
Clone Graph
Given a reference of a node in a connected undirected graph. Return a deep copy (clone) of the graph. Tags: Graph
Try It!
Discussion
Video
Solution
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""
from collections import deque
class Solution:
def cloneGraph(self, node: 'Node') -> 'Node':
if not node:
return None
# Dictionary to store the mapping of original nodes to cloned nodes
clones = {}
# Create a clone of the starting node
clones[node] = Node(node.val)
# Queue for BFS traversal
queue = deque([node])
while queue:
curr = queue.popleft()
# Iterate over the neighbors of the current node
for neighbor in curr.neighbors:
if neighbor not in clones:
# Create a clone of the neighbor if it doesn't exist
clones[neighbor] = Node(neighbor.val)
queue.append(neighbor)
# Add the cloned neighbor to the cloned node's neighbors list
clones[curr].neighbors.append(clones[neighbor])
return clones[node]