DFS, or Depth First Search, is a traversal algorithm used to explore graphs and trees. It starts from the root and explores each branch as far as possible before backtracking. This algorithm can be used to perform tree traversal in pre-order, in-order, and post-order. Often, the Stack data structure is used for DFS traversal.
BFS stands for Breadth-First Search, which is also known as level order traversal. As the name suggests, after traversing all the nodes in the current level, it will move on to the next level. Usually, the Queue data structure is used for the BFS traversal.
You can get a clear view of how DFS and BFS traverse a tree through the graph below:

Below is a list of practice problems from Leetcode about DFS and BFS. Happy coding!😄
• DFS
https://leetcode.com/problems/sum-root-to-leaf-numbers/
class Solution:
def sumNumbers(self, root: Optional[TreeNode]) -> int:
def dfs(node, num):
if node is None:
return 0
num = num * 10 + node.val
if node.left == None and node.right == None:
return num
return dfs(node.left, num) + dfs(node.right, num)
return dfs(root, 0)
https://leetcode.com/problems/path-sum-ii/
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
ans = []
def dfs(node, curSum, cur):
if node == None:
return
cur.append(node.val)
curSum += node.val
if node.left == None and node.right == None and curSum == targetSum:
ans.append(cur.copy())
dfs(node.left, curSum, cur)
dfs(node.right, curSum, cur)
cur.pop()
dfs(root, 0, [])
return ans
https://leetcode.com/problems/path-sum-iii/
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> int:
self.ans = 0
lookup = {}
def dfs(node, curSum):
if node == None:
return
curSum += node.val
if curSum == targetSum:
self.ans += 1
if curSum - targetSum in lookup:
self.ans += lookup[curSum - targetSum]
lookup[curSum] = lookup.get(curSum, 0) + 1
dfs(node.left, curSum)
dfs(node.right, curSum)
lookup[curSum] -= 1
dfs(root, 0)
return self.ans
https://leetcode.com/problems/binary-tree-paths/
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
ans = []
def dfs(node, temp):
if node is None:
return []
if node.left == None and node.right == None:
return ans.append(temp + str(node.val))
temp += str(node.val) + "->"
dfs(node.left, temp)
dfs(node.right, temp)
dfs(root, "")
return ans
https://leetcode.com/problems/smallest-string-starting-from-leaf/
class Solution:
def smallestFromLeaf(self, root: Optional[TreeNode]) -> str:
self.ans = 'z' + chr(1)
def dfs(node, s):
if node == None:
return
s += chr(ord('a') + node.val)
if node.left == None and node.right == None:
self.ans = min(self.ans, s[::-1])
dfs(node.left, s)
dfs(node.right, s)
s = s[:-1]
dfs(root, "")
return self.ans
https://leetcode.com/problems/diameter-of-binary-tree/
class Solution:
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
self.ans = 0
def dfs(root):
if root == None:
return 0
l, r = dfs(root.left), dfs(root.right)
self.ans = max((l + r), self.ans)
return max(l, r) + 1
dfs(root)
return self.ans
https://leetcode.com/problems/binary-tree-maximum-path-sum/
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:
self.ans = float('-inf')
def dfs(node):
if node == None:
return 0
l, r = dfs(node.left), dfs(node.right)
self.ans = max(self.ans, l + r + node.val)
return max(0, max(l, r) + node.val)
dfs(root)
return self.ans
https://leetcode.com/problems/longest-univalue-path/
class Solution:
def longestUnivaluePath(self, root: Optional[TreeNode]) -> int:
self.ans = 0
def dfs(node):
if node == None:
return 0
l, r = dfs(node.left), dfs(node.right)
L, R = 0, 0
if node.left != None and node.left.val == node.val:
L = l
if node.right != None and node.right.val == node.val:
R = r
self.ans = max(self.ans, L + R)
return max(L, R) + 1
dfs(root)
return self.ans
https://leetcode.com/problems/n-ary-tree-preorder-traversal/
class Solution:
def preorder(self, root: 'Node') -> List[int]:
self.ans = []
def dfs(node):
if node == None:
return
self.ans.append(node.val)
for child in node.children:
dfs(child)
dfs(root)
return self.ans
https://leetcode.com/problems/n-ary-tree-postorder-traversal/
class Solution:
def postorder(self, root: 'Node') -> List[int]:
self.ans = []
def dfs(node):
if node == None:
return
for child in node.children:
dfs(child)
self.ans.append(node.val)
dfs(root)
return self.ans
https://leetcode.com/problems/minimum-depth-of-binary-tree/
class Solution:
def minDepth(self, root: Optional[TreeNode]) -> int:
self.ans = float("inf")
if root == None:
return 0
def dfs(node, dep):
if node == None:
return 0
if node.left == None and node.right == None:
self.ans = min(self.ans, dep)
dfs(node.left, dep + 1)
dfs(node.right, dep + 1)
dfs(root, 1)
return self.ans
https://leetcode.com/problems/balanced-binary-tree/
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
def dfs(node):
if node == None:
return 0
l, r = dfs(node.left), dfs(node.right)
if l == -1:
return -1
if r == -1:
return -1
if abs(l - r) > 1:
return -1
return max(l, r) + 1
return dfs(root) != -1
https://leetcode.com/problems/increasing-order-search-tree/
class Solution:
def increasingBST(self, root: TreeNode) -> TreeNode:
dummy = TreeNode(-1)
self.cur = dummy
def dfs(node):
if node == None:
return
dfs(node.left)
self.cur.right = node
node.left = None
self.cur = self.cur.right
dfs(node.right)
dfs(root)
return dummy.right
https://leetcode.com/problems/sum-of-left-leaves/
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
self.ans = 0
def dfs(node):
if node == None:
return 0
if node.left != None and node.left.left == None and node.left.right == None:
self.ans += node.left.val
dfs(node.left)
dfs(node.right)
dfs(root)
return self.ans
https://leetcode.com/problems/binary-tree-pruning/
class Solution:
def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def dfs(node):
if not node:
return False
l, r = dfs(node.left), dfs(node.right)
if not l:
node.left = None
if not r:
node.right = None
return l or r or node.val == 1
return root if dfs(root) else None
https://leetcode.com/problems/binary-tree-longest-consecutive-sequence/
class Solution:
def longestConsecutive(self, root: Optional[TreeNode]) -> int:
self.max = 1
def dfs(node, cnt):
self.max = max(self.max, cnt)
if node.left:
if node.left.val == node.val + 1:
dfs(node.left, cnt + 1)
else:
dfs(node.left, 1)
if node.right:
if node.right.val == node.val + 1:
dfs(node.right, cnt + 1)
else:
dfs(node.right, 1)
dfs(root, 1)
return self.max
https://leetcode.com/problems/binary-tree-longest-consecutive-sequence-ii/
class Solution:
def longestConsecutive(self, root: Optional[TreeNode]) -> int:
self.max = 0
def dfs(node):
if node == None:
return [0, 0]
l, r = dfs(node.left), dfs(node.right)
inc, dec = 1, 1
if node.left:
if node.val == node.left.val + 1:
dec = l[1] + 1
if node.val == node.left.val - 1:
inc = l[0] + 1
if node.right:
if node.val == node.right.val + 1:
dec = max(dec, r[1] + 1)
if node.val == node.right.val - 1:
inc = max(inc, r[0] + 1)
self.max = max(self.max, inc + dec - 1)
return [inc, dec]
dfs(root)
return self.max
https://leetcode.com/problems/maximum-width-of-binary-tree/
class Solution:
def widthOfBinaryTree(self, root: Optional[TreeNode]) -> int:
self.max = 0
pos = []
def dfs(node, dep, p):
if node == None:
return
if dep == len(pos):
pos.append(p)
self.max = max(self.max, p - pos[dep] + 1)
dfs(node.left, dep + 1, p * 2 + 1)
dfs(node.right, dep + 1, p * 2 + 2)
dfs(root, 0, 0)
return self.max
https://leetcode.com/problems/maximum-product-of-splitted-binary-tree/
class Solution:
def maxProduct(self, root: Optional[TreeNode]) -> int:
self.total = 0
self.ans = 0
def dfs1(node):
if node == None:
return
self.total += node.val
dfs1(node.left)
dfs1(node.right)
def dfs2(node):
if node == None:
return 0
l, r = dfs2(node.left), dfs2(node.right)
self.ans = max(self.ans, max(l * (self.total - l), r * (self.total - r)))
return node.val + l + r
dfs1(root)
dfs2(root)
return self.ans % (10 ** 9 + 7)
https://leetcode.com/problems/find-mode-in-binary-search-tree/
class Solution:
def findMode(self, root: Optional[TreeNode]) -> List[int]:
self.pre = root.val
self.cur, self.max = 0, 0
self.ans = []
def dfs(node):
if node == None:
return
dfs(node.left)
if node.val != self.pre:
self.cur = 1
self.pre = node.val
else:
self.cur += 1
if self.cur > self.max:
self.max = self.cur
self.ans.clear()
self.ans.append(node.val)
elif self.cur == self.max:
self.ans.append(node.val)
dfs(node.right)
dfs(root)
return self.ans
https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
def dfs(left, right):
if left > right:
return None
mid = (left + right) // 2
root = TreeNode(nums[mid])
root.left = dfs(left, mid - 1)
root.right = dfs(mid + 1, right)
return root
return dfs(0, len(nums) - 1)
https://leetcode.com/problems/kth-smallest-element-in-a-bst/
class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
self.ans = None
self.k = k
def dfs(node):
if node is None:
return
dfs(node.left)
self.k -= 1
if self.k == 0:
self.ans = node.val
return
dfs(node.right)
dfs(root)
return self.ans
https://leetcode.com/problems/recover-binary-search-tree/
class Solution:
def recoverTree(self, root: Optional[TreeNode]) -> None:
arr = []
def dfs(node):
if node == None:
return
dfs(node.left)
arr.append(node)
dfs(node.right)
dfs(root)
a = None
b = None
for i in range(0, len(arr)):
if arr[i].val > arr[i + 1].val:
a = arr[i]
break
for i in range(len(arr) - 1, -1, -1):
if arr[i].val < arr[i - 1].val:
b = arr[i]
break
a.val, b.val = b.val, a.val
https://leetcode.com/problems/inorder-successor-in-bst/
class Solution:
def inorderSuccessor(self, root: TreeNode, p: TreeNode) -> Optional[TreeNode]:
self.ans = None
self.flag = False
def dfs(node):
if node == None:
return
dfs(node.left)
if self.flag and self.ans == None:
self.ans = node
if not self.flag and node == p:
self.flag = True
dfs(node.right)
dfs(root)
return self.ans
https://leetcode.com/problems/closest-binary-search-tree-value-ii/
class Solution:
def closestKValues(self, root: Optional[TreeNode], target: float, k: int) -> List[int]:
self.q = deque()
def dfs(node):
if node == None:
return
dfs(node.left)
if len(self.q) < k:
self.q.append(node.val)
elif abs(self.q[0] - target) > abs(node.val - target):
self.q.popleft()
self.q.append(node.val)
dfs(node.right)
dfs(root)
return self.q
https://leetcode.com/problems/generate-parentheses/
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
def dfs(u, l, r, cur):
if u == 2 * n:
return ans.append(cur)
if r < l: dfs(u + 1, l, r + 1, cur + ")")
if l < n: dfs(u + 1, l + 1, r, cur + "(")
ans = []
dfs(0, 0, 0, "")
return ans
https://leetcode.com/problems/throne-inheritance/
class ThroneInheritance:
def __init__(self, kingName: str):
self.g = defaultdict(list)
self.kingName = kingName
self.dead = set()
def birth(self, parentName: str, childName: str) -> None:
self.g[parentName].append(childName)
def death(self, name: str) -> None:
self.dead.add(name)
def getInheritanceOrder(self) -> List[str]:
def dfs(u):
if u not in self.dead:
ans.append(u)
for v in self.g[u]:
dfs(v)
ans = []
dfs(self.kingName)
return ans
https://leetcode.com/problems/number-of-enclaves/
class Solution:
def numEnclaves(self, grid: List[List[int]]) -> int:
def dfs(i, j):
grid[i][j] = 0
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == 1:
dfs(ni, nj)
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 1 and (i == 0 or j == 0 or i == m - 1 or j == n - 1):
dfs(i, j)
return sum(sum(row) for row in grid)
https://leetcode.com/problems/validate-binary-tree-nodes/
class Solution:
def validateBinaryTreeNodes(self, n: int, leftChild: List[int], rightChild: List[int]) -> bool:
def dfs(u):
vis.add(u)
if leftChild[u] != -1:
if leftChild[u] in vis or not dfs(leftChild[u]):
return False
if rightChild[u] != -1:
if rightChild[u] in vis or not dfs(rightChild[u]):
return False
return True
d = [0] * n
for x in leftChild + rightChild:
if x != -1:
d[x] += 1
if d[x] > 1:
return False
if d.count(0) != 1:
return False
root = d.index(0)
vis = set()
if not dfs(root):
return False
return len(vis) == n
https://leetcode.com/problems/number-of-islands/
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
def dfs(i, j):
grid[i][j] = '0'
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == '1':
dfs(ni, nj)
ans = 0
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == '1':
ans += 1
dfs(i, j)
return ans
https://leetcode.com/problems/count-sub-islands/
class Solution:
def countSubIslands(self, grid1: List[List[int]], grid2: List[List[int]]) -> int:
def dfs(i, j):
nonlocal isSub
grid2[i][j] = 0
if grid1[i][j] == 0:
isSub = False
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid2[ni][nj] == 1:
dfs(ni, nj)
ans = 0
m, n = len(grid1), len(grid1[0])
for i in range(m):
for j in range(n):
if grid2[i][j] == 1:
isSub = True
dfs(i, j)
if isSub:
ans += 1
return ans
https://leetcode.com/problems/count-servers-that-communicate/
class Solution:
def countServers(self, grid: List[List[int]]) -> int:
def dfs(i, j):
nonlocal cnt
cnt += 1
vis.add((i, j))
for ni, nj in g1[i] + g2[j]:
if (ni, nj) not in vis:
dfs(ni, nj)
g1 = defaultdict(list)
g2 = defaultdict(list)
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
g1[i].append([i, j])
g2[j].append([i, j])
vis = set()
ans = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 1 and (i, j) not in vis:
cnt = 0
dfs(i, j)
if cnt > 1:
ans += cnt
return ans
https://leetcode.com/problems/word-search/
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
def dfs(i, j, u):
if board[i][j] != word[u]: return False
if u == len(word) - 1: return True
t = board[i][j]
board[i][j] = '#'
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and board[ni][nj] != '#':
if dfs(ni, nj, u + 1): return True
board[i][j] = t
return False
m, n = len(board), len(board[0])
for i in range(m):
for j in range(n):
if dfs(i, j, 0): return True
return False
https://leetcode.com/problems/surrounded-regions/
class Solution:
def solve(self, board: List[List[str]]) -> None:
def dfs(i, j):
board[i][j] = '#'
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and board[ni][nj] == 'O':
dfs(ni, nj)
m, n = len(board), len(board[0])
for i in range(m):
for j in range(n):
if (i == 0 or j == 0 or i == m - 1 or j == n - 1) and board[i][j] == 'O':
dfs(i, j)
for i in range(m):
for j in range(n):
if board[i][j] == '#': board[i][j] = 'O'
elif board[i][j] == 'O': board[i][j] = 'X'
https://leetcode.com/problems/clone-graph/
class Solution:
def cloneGraph(self, node: 'Node') -> 'Node':
def dfs(node):
if node is None:
return None
if node not in d:
d[node] = Node(node.val)
for v in node.neighbors:
d[node].neighbors.append(dfs(v))
return d[node]
d = {}
return dfs(node)
https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/
class Solution:
def countComponents(self, n: int, edges: List[List[int]]) -> int:
def dfs(u):
vis.add(u)
for v in g[u]:
if v not in vis:
dfs(v)
ans = 0
g = defaultdict(list)
vis = set()
for u, v in edges:
g[u].append(v)
g[v].append(u)
for i in range(n):
if i not in vis:
ans += 1
dfs(i)
return ans
https://leetcode.com/problems/pacific-atlantic-water-flow/
class Solution:
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
def dfs(i, j, h):
h.add((i, j))
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and heights[ni][nj] >= heights[i][j] and (ni, nj) not in h:
dfs(ni, nj, h)
m, n = len(heights), len(heights[0])
h1, h2 = set(), set()
for i in range(m):
for j in range(n):
if i == 0 or j == 0: dfs(i, j, h1)
if i == m - 1 or j == n - 1: dfs(i, j, h2)
return list(h1 & h2)
https://leetcode.com/problems/the-maze/
class Solution:
def hasPath(self, maze: List[List[int]], start: List[int], destination: List[int]) -> bool:
def dfs(i, j):
if [i, j] == destination:
return True
vis.add((i, j))
for d in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
ni, nj = i, j
while 0 <= ni + d[0] < m and 0 <= nj + d[1] < n and maze[ni + d[0]][nj + d[1]] == 0:
ni, nj = ni + d[0], nj + d[1]
if (ni, nj) not in vis and dfs(ni, nj):
return True
return False
m, n = len(maze), len(maze[0])
vis = set()
return dfs(start[0], start[1])
https://leetcode.com/problems/number-of-distinct-islands/
class Solution:
def numDistinctIslands(self, grid: List[List[int]]) -> int:
def dfs(i, j):
nonlocal path
grid[i][j] = 0
for ni, nj, d in [(i - 1, j, 'u'), (i + 1, j, 'd'), (i, j - 1, 'l'), (i, j + 1, 'r')]:
path += d
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == 1:
dfs(ni, nj)
m, n = len(grid), len(grid[0])
ans = set()
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
path = ''
dfs(i, j)
ans.add(path)
return len(ans)
https://leetcode.com/problems/max-area-of-island/
class Solution:
def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
def dfs(i, j):
nonlocal cnt
grid[i][j] = 0
cnt += 1
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == 1:
dfs(ni, nj)
ans = 0
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
cnt = 0
dfs(i, j)
ans = max(cnt, ans)
return ans
https://leetcode.com/problems/keys-and-rooms/
class Solution:
def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
def dfs(u):
vis.add(u)
for v in rooms[u]:
if v not in vis:
dfs(v)
vis = set()
dfs(0)
return len(vis) == len(rooms)
https://leetcode.com/problems/nested-list-weight-sum/
class Solution:
def depthSum(self, nestedList: List[NestedInteger]) -> int:
def dfs(cur, dep):
nonlocal ans
for x in cur:
if x.isInteger():
ans += dep * x.getInteger()
else:
dfs(x.getList(), dep + 1)
ans = 0
dfs(nestedList, 1)
return ans
https://leetcode.com/problems/employee-importance/
class Solution:
def getImportance(self, employees: List['Employee'], id: int) -> int:
def dfs(u):
nonlocal ans
ans += d[u].importance
for v in d[u].subordinates:
dfs(v)
ans = 0
d = {}
for e in employees:
d[e.id] = e
dfs(id)
return ans
https://leetcode.com/problems/all-paths-from-source-to-target/
class Solution:
def allPathsSourceTarget(self, graph: List[List[int]]) -> List[List[int]]:
def dfs(u, path):
nonlocal ans
path.append(u)
if u == len(graph) - 1:
ans.append(path[::])
for v in graph[u]:
dfs(v, path)
path.pop()
ans = []
dfs(0, [])
return ans
https://leetcode.com/problems/jump-game-iii/
class Solution:
def canReach(self, arr: List[int], start: int) -> bool:
def dfs(i):
if arr[i] == 0:
return True
vis.add(i)
ans = False
if i + arr[i] < len(arr) and i + arr[i] not in vis:
ans |= dfs(i + arr[i])
if i - arr[i] >= 0 and i - arr[i] not in vis:
ans |= dfs(i - arr[i])
return ans
vis = set()
return dfs(start)
https://leetcode.com/problems/number-of-closed-islands/
class Solution:
def closedIsland(self, grid: List[List[int]]) -> int:
def dfs(i, j):
grid[i][j] = 1
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == 0:
dfs(ni, nj)
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if (i == 0 or j == 0 or i == m - 1 or j == n - 1) and grid[i][j] == 0:
dfs(i, j)
ans = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 0:
ans += 1
dfs(i, j)
return ans
https://leetcode.com/problems/reorder-routes-to-make-all-paths-lead-to-the-city-zero/
class Solution:
def minReorder(self, n: int, connections: List[List[int]]) -> int:
def dfs(u):
nonlocal ans
vis.add(u)
for v in g[u]:
if v not in vis:
if (u, v) not in origin:
ans += 1
dfs(v)
origin = set((u, v) for u, v in connections)
g = defaultdict(list)
for u, v in connections:
g[u].append(v)
g[v].append(u)
ans = 0
vis = set()
dfs(0)
return len(connections) - ans
https://leetcode.com/problems/number-of-operations-to-make-network-connected/
class Solution:
def makeConnected(self, n: int, connections: List[List[int]]) -> int:
def dfs(u):
vis.add(u)
for v in g[u]:
if v not in vis:
dfs(v)
if len(connections) < n - 1:
return -1
g = defaultdict(list)
for u, v in connections:
g[u].append(v)
g[v].append(u)
ans = 0
vis = set()
for i in range(n):
if i not in vis:
ans += 1
dfs(i)
return ans - 1
https://leetcode.com/problems/possible-bipartition/
class Solution:
def possibleBipartition(self, n: int, dislikes: List[List[int]]) -> bool:
def dfs(u, c):
if u in color:
return color[u] == c
color[u] = c
for v in g[u]:
if not dfs(v, c ^ 1):
return False
return True
color = {}
g = defaultdict(list)
for u, v in dislikes:
g[u].append(v)
g[v].append(u)
for i in range(1, n + 1):
if i not in color and not dfs(i, 0):
return False
return True
https://leetcode.com/problems/kill-process/
class Solution:
def killProcess(self, pid: List[int], ppid: List[int], kill: int) -> List[int]:
def dfs(u):
ans.append(u)
for v in g[u]:
dfs(v)
n = len(pid)
g = defaultdict(list)
for i in range(n):
g[ppid[i]].append(pid[i])
ans = []
dfs(kill)
return ans
https://leetcode.com/problems/time-needed-to-inform-all-employees/
class Solution:
def numOfMinutes(self, n: int, headID: int, manager: List[int], informTime: List[int]) -> int:
def dfs(u, time):
nonlocal ans
ans = max(ans, time)
for v in g[u]:
dfs(v, time + informTime[u])
ans = 0
g = defaultdict(list)
for i in range(n):
g[manager[i]].append(i)
dfs(headID, 0)
return ans
https://leetcode.com/problems/lexicographical-numbers/
class Solution:
def lexicalOrder(self, n: int) -> List[int]:
def dfs(u):
for i in range(1 if u == 0 else 0, min(9, n) + 1):
if u + i <= n:
ans.append(u + i)
if (u + i) * 10 <= n:
dfs((u + i) * 10)
ans = []
dfs(0)
return ans
https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/
class Solution:
def removeStones(self, stones: List[List[int]]) -> int:
def dfs(r, c):
vis.add((r, c))
for nr, nc in g1[r] + g2[c]:
if (nr, nc) not in vis:
dfs(nr, nc)
g1 = defaultdict(list)
g2 = defaultdict(list)
for r, c in stones:
g1[r].append([r, c])
g2[c].append([r, c])
ans = 0
vis = set()
for r, c in stones:
if (r, c) not in vis:
ans += 1
dfs(r, c)
return len(stones) - ans
https://leetcode.com/problems/sentence-similarity-ii/
class Solution:
def areSentencesSimilarTwo(self, sentence1: List[str], sentence2: List[str], similarPairs: List[List[str]]) -> bool:
def dfs(u, target):
if u == target:
return True
vis.add(u)
for v in g[u]:
if v not in vis and dfs(v, target):
return True
return False
if len(sentence1) != len(sentence2):
return False
g = defaultdict(list)
for u, v in similarPairs:
g[u].append(v)
g[v].append(u)
for u, v in zip(sentence1, sentence2):
vis = set()
if not dfs(u, v):
return False
return True
https://leetcode.com/problems/evaluate-division/
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
def dfs(x, y, i, cur):
if x == y:
ans[i] = cur
return
vis.add(x)
for z, val in g[x]:
if z not in vis:
dfs(z, y, i, cur * val)
g = defaultdict(list)
for (x, y), z in zip(equations, values):
g[x].append((y, z))
g[y].append((x, 1/z))
ans = [-1] * len(queries)
for i, (x, y) in enumerate(queries):
vis = set()
if x in g and y in g:
dfs(x, y, i, 1)
return ans
https://leetcode.com/problems/letter-combinations-of-a-phone-number/
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if digits == "":
return []
d = {
"2": "abc",
"3": "def",
"4": "ghi",
"5": "jkl",
"6": "mno",
"7": "pqrs",
"8": "tuv",
"9": "wxyz"
}
ans = []
def dfs(cur, j):
if j == len(digits):
return ans.append(cur)
for v in d[digits[j]]:
dfs(cur + str(v), j + 1)
dfs("", 0)
return ans
https://leetcode.com/problems/unique-paths-iii/
class Solution:
def uniquePathsIII(self, grid: List[List[int]]) -> int:
def dfs(i, j):
nonlocal ans
if i == er and j == ec:
if len(vis) + 1 == m * n - block:
ans += 1
return
vis.add((i, j))
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] != -1 and (ni, nj) not in vis:
dfs(ni, nj)
vis.remove((i, j))
ans = 0
vis = set()
block = 0
sr, sc, er, ec = 0, 0, 0, 0
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
sr, sc = i, j
if grid[i][j] == 2:
er, ec = i, j
if grid[i][j] == -1:
block += 1
dfs(sr, sc)
return ans
https://leetcode.com/problems/is-graph-bipartite/
class Solution:
def isBipartite(self, graph: List[List[int]]) -> bool:
def dfs(u, c):
if u in vis:
return vis[u] == c
vis[u] = c
for v in graph[u]:
if not dfs(v, c ^ 1):
return False
return True
vis = {}
n = len(graph)
for i in range(n):
if i not in vis:
if not dfs(i, 0):
return False
return True
https://leetcode.com/problems/coloring-a-border/
class Solution:
def colorBorder(self, grid: List[List[int]], row: int, col: int, color: int) -> List[List[int]]:
def dfs(i, j):
t[i][j] = True
grid[i][j] = color
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == old:
dfs(ni, nj)
if grid[row][col] == color:
return grid
m, n = len(grid), len(grid[0])
old = grid[row][col]
t = [[False] * n for _ in range(m)]
dfs(row, col)
for i in range(1, m - 1):
for j in range(1, n - 1):
if t[i][j] and t[i - 1][j] and t[i + 1][j] and t[i][j - 1] and t[i][j + 1]:
grid[i][j] = old
return grid
https://leetcode.com/problems/detect-cycles-in-2d-grid/
class Solution:
def containsCycle(self, grid: List[List[str]]) -> bool:
def dfs(i, j, pi, pj):
vis.add((i, j))
for ni, nj in [(i-1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == grid[i][j] and (ni, nj) != (pi, pj):
if (ni, nj) in vis or dfs(ni, nj, i, j):
return True
return False
m, n = len(grid), len(grid[0])
vis = set()
for i in range(m):
for j in range(n):
if (i, j) not in vis:
if dfs(i, j, -1, -1):
return True
return False
https://leetcode.com/problems/shortest-bridge/
class Solution:
def shortestBridge(self, grid: List[List[int]]) -> int:
def dfs(i, j):
heapq.heappush(q, (0, i, j))
vis.add((i, j))
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and grid[ni][nj] == 1 and (ni, nj) not in vis:
dfs(ni, nj)
def bfs():
while q:
x, i, j = heapq.heappop(q)
if x > 0 and grid[i][j] == 1:
return x - 1
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis:
vis.add((ni, nj))
heapq.heappush(q, (x + 1, ni, nj))
m, n = len(grid), len(grid[0])
q = []
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
vis = set()
dfs(i, j)
return bfs()
https://leetcode.com/problems/minesweeper/
class Solution:
def updateBoard(self, board: List[List[str]], click: List[int]) -> List[List[str]]:
def dfs(i, j):
cnt = 0
for d in dirs:
ni, nj = i + d[0], j + d[1]
if 0 <= ni < m and 0 <= nj < n and board[ni][nj] == 'M':
cnt += 1
if cnt == 0:
board[i][j] = 'B'
for d in dirs:
ni, nj = i + d[0], j + d[1]
if 0 <= ni < m and 0 <= nj < n and board[ni][nj] == 'E':
dfs(ni, nj)
else:
board[i][j] = str(cnt)
dirs = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
m, n = len(board), len(board[0])
i, j = click
if board[i][j] == 'M':
board[i][j] = 'X'
else:
dfs(i, j)
return board
https://leetcode.com/problems/number-of-provinces/
class Solution:
def findCircleNum(self, isConnected: List[List[int]]) -> int:
def dfs(i):
vis.add(i)
for j in range(n):
if isConnected[i][j] and j not in vis:
dfs(j)
ans = 0
n = len(isConnected)
vis = set()
for i in range(n):
if i not in vis:
dfs(i)
ans += 1
return ans
https://leetcode.com/problems/all-paths-from-source-lead-to-destination/
class Solution:
def leadsToDestination(self, n: int, edges: List[List[int]], source: int, destination: int) -> bool:
@lru_cache(None)
def dfs(u):
if not g[u]:
return u == destination
vis.add(u)
for v in g[u]:
if v in vis or not dfs(v):
return False
vis.remove(u)
return True
vis = set()
g = defaultdict(list)
for u, v in edges:
g[u].append(v)
return dfs(source)
https://leetcode.com/problems/smallest-common-region/
class Solution:
def findSmallestRegion(self, regions: List[List[str]], region1: str, region2: str) -> str:
def dfs(u):
if u == region1 or u == region2:
return u
ans = set()
for v in g[u]:
t = dfs(v)
if t:
ans.add(t)
if len(ans) == 2:
return u
return ans.pop() if len(ans) == 1 else None
g = defaultdict(list)
sub = set()
for region in regions:
for i in range(1, len(region)):
g[region[0]].append(region[i])
sub.add(region[i])
for region in regions:
if region[0] not in sub:
return dfs(region[0])
https://leetcode.com/problems/regions-cut-by-slashes/
class Solution:
def regionsBySlashes(self, grid: List[str]) -> int:
def dfs(i, j):
g[i][j] = 1
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m * 3 and 0 <= nj < n * 3 and g[ni][nj] == 0:
dfs(ni, nj)
m, n = len(grid), len(grid[0])
g = [[0] * n * 3 for _ in range(m * 3)]
for i in range(m):
for j in range(n):
if grid[i][j] == '/':
for k in range(3):
g[i * 3 + k][j * 3 + 2 - k] = 1
elif grid[i][j] == '\\':
for k in range(3):
g[i * 3 + k][j * 3 + k] = 1
ans = 0
for i in range(m * 3):
for j in range(n * 3):
if g[i][j] == 0:
ans += 1
dfs(i, j)
return ans
https://leetcode.com/problems/pyramid-transition-matrix/
class Solution:
def pyramidTransition(self, bottom: str, allowed: List[str]) -> bool:
@lru_cache(None)
def dfs(s, i):
if len(s) == 1:
return True
if i == len(s) - 1:
return dfs(s[:-1], 0)
for c in g[s[i: i + 2]]:
if dfs(s[:i] + c + s[i + 1:], i + 1):
return True
return False
g = defaultdict(list)
for s in allowed:
g[s[:2]].append(s[-1])
return dfs(bottom, 0)
https://leetcode.com/problems/loud-and-rich/
class Solution:
def loudAndRich(self, richer: List[List[int]], quiet: List[int]) -> List[int]:
@lru_cache(None)
def dfs(u):
if not g[u]:
return [quiet[u], u]
t = min(dfs(v) for v in g[u])
t = min(t, [quiet[u], u])
if quiet[ans[u]] > quiet[t[1]]:
ans[u] = t[1]
return t
n = len(quiet)
ans = list(range(n))
g = defaultdict(list)
for u, v in richer:
g[v].append(u)
for i in range(n):
dfs(i)
return ans
https://leetcode.com/problems/check-if-there-is-a-valid-path-in-a-grid/
class Solution:
def hasValidPath(self, grid: List[List[int]]) -> bool:
def dfs(i, j, d):
if i == m - 1 and j == n - 1:
return True
vis.add((i, j))
ni, nj = i + dirs[d][0], j + dirs[d][1]
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis and g[grid[ni][nj]][d] != -1:
if dfs(ni, nj, g[grid[ni][nj]][d]):
return True
return False
# 0 up 1 right 2 down 3 left
g = [[], [-1, 1, -1, 3], [0, -1, 2, -1], [3, 2, -1, -1], [1, -1, -1, 2], [-1, 0, 3, -1], [-1, -1, 1, 0]]
m, n = len(grid), len(grid[0])
vis = set()
dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]]
for i in range(4):
if dfs(0, 0, i):
return True
return False
https://leetcode.com/problems/flower-planting-with-no-adjacent/
class Solution:
def gardenNoAdj(self, n: int, paths: List[List[int]]) -> List[int]:
ans = [0] * n
g = defaultdict(list)
for u, v in paths:
g[u - 1].append(v - 1)
g[v - 1].append(u - 1)
for i in range(n):
ans[i] = ({1, 2, 3, 4} - {ans[j] for j in g[i]}).pop()
return ans
https://leetcode.com/problems/nested-list-weight-sum-ii/
class Solution:
def depthSumInverse(self, nestedList: List[NestedInteger]) -> int:
def getDep(cur, u):
nonlocal mx
mx = max(mx, u)
for v in cur:
if not v.isInteger() and v.getList():
getDep(v.getList(), u + 1)
def dfs(cur, u):
nonlocal ans
for v in cur:
if v.isInteger():
ans += v.getInteger() * (mx - u + 1)
else:
dfs(v.getList(), u + 1)
mx = 0
getDep(nestedList, 1)
ans = 0
dfs(nestedList, 1)
return ans
• BFS
https://leetcode.com/problems/letter-combinations-of-a-phone-number/
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
if digits == "":
return []
s = ["", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" ]
a = [""]
for c in digits:
b = []
for cur in a:
for ch in s[int(c)]:
b.append(cur + ch)
a = b
return a
https://leetcode.com/problems/brace-expansion/
class Solution:
def expand(self, s: str) -> List[str]:
n = len(s)
a = ['']
i = 0
while i < n:
b = []
if s[i] == '{':
j = s.find('}', i)
t = [c for c in s[i + 1: j] if c.isalpha()]
i = j + 1
else:
t = s[i]
i = i + 1
for c in t:
for cur in a:
b.append(cur + c)
a = b
return sorted(a)
https://leetcode.com/problems/rotting-oranges/
class Solution:
def orangesRotting(self, grid: List[List[int]]) -> int:
q = deque()
m, n = len(grid), len(grid[0])
for i in range(m):
for j in range(n):
if grid[i][j] == 2:
q.append([i, j, 0])
time = 0
while q:
x, y, time = q.popleft()
for nx, ny in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]:
if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 1:
grid[nx][ny] = 2
q.append([nx, ny, time + 1])
for g in grid:
if 1 in g:
return -1
return time
https://leetcode.com/problems/shortest-path-to-get-food/
class Solution:
def getFood(self, grid: List[List[str]]) -> int:
m, n = len(grid), len(grid[0])
vis = set()
q = deque()
for i in range(m):
for j in range(n):
if grid[i][j] == 'X':
vis.add((i, j))
elif grid[i][j] == '*':
vis.add((i, j))
q.append((i, j, 0))
while q:
i, j, k = q.popleft()
if grid[i][j] == '#':
return k
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis:
vis.add((ni, nj))
q.append((ni, nj, k + 1))
return -1
https://leetcode.com/problems/minimum-knight-moves/
class Solution:
def minKnightMoves(self, x: int, y: int) -> int:
dirs = [[-2, 1], [-1, 2], [1, 2], [2, 1], [2, -1], [1, -2], [-1, -2], [-2, -1]]
q = deque()
vis = set()
q.append((0, 0, 0))
while q:
i, j, k = q.popleft()
if i == x and j == y:
return k
for a, b in dirs:
ni, nj = i + a, j + b
if (ni, nj) not in vis:
vis.add((ni, nj))
q.append((ni, nj, k + 1))
https://leetcode.com/problems/nearest-exit-from-entrance-in-maze/
class Solution:
def nearestExit(self, maze: List[List[str]], entrance: List[int]) -> int:
m, n = len(maze), len(maze[0])
q = deque()
q.append((entrance[0], entrance[1], 0))
vis = {(entrance[0], entrance[1])}
while q:
i, j, k = q.popleft()
if (i == 0 or j == 0 or i == m - 1 or j == n - 1) and [i, j] != entrance:
return k
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis and maze[ni][nj] == '.':
q.append((ni, nj, k + 1))
vis.add((ni, nj))
return -1
https://leetcode.com/problems/minimum-operations-to-convert-number/
class Solution:
def minimumOperations(self, nums: List[int], start: int, goal: int) -> int:
q = deque()
q.append((start, 0))
vis = {start}
while q:
u, k = q.popleft()
if u == goal:
return k
for x in nums:
for v in [u + x, u - x, u ^ x]:
if v == goal:
return k + 1
if 0 <= v <= 1000 and v not in vis:
q.append((v, k + 1))
vis.add(v)
return -1
https://leetcode.com/problems/01-matrix/
class Solution:
def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
m, n = len(mat), len(mat[0])
g = [[0] * n for _ in range(m)]
q = deque()
vis = set()
for i in range(m):
for j in range(n):
if mat[i][j] == 0:
vis.add((i, j))
q.append((i, j, 0))
while q:
i, j, k = q.popleft()
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis:
vis.add((ni, nj))
q.append((ni, nj, k + 1))
g[ni][nj] = k + 1
return g
https://leetcode.com/problems/map-of-highest-peak/
class Solution:
def highestPeak(self, isWater: List[List[int]]) -> List[List[int]]:
m, n = len(isWater), len(isWater[0])
g = [[0] * n for _ in range(m)]
q = deque()
vis = set()
for i in range(m):
for j in range(n):
if isWater[i][j] == 1:
q.append((i, j, 0))
vis.add((i, j))
while q:
i, j, k = q.popleft()
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis:
g[ni][nj] = k + 1
q.append((ni, nj, k + 1))
vis.add((ni, nj))
return g
https://leetcode.com/problems/walls-and-gates/
class Solution:
def wallsAndGates(self, rooms: List[List[int]]) -> None:
m, n = len(rooms), len(rooms[0])
q = deque()
vis = set()
for i in range(m):
for j in range(n):
if rooms[i][j] == 0:
vis.add((i, j))
q.append((i, j, 0))
elif rooms[i][j] == -1:
vis.add((i, j))
while q:
i, j, k = q.popleft()
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis:
vis.add((ni, nj))
q.append((ni, nj, k + 1))
rooms[ni][nj] = k + 1
https://leetcode.com/problems/as-far-from-land-as-possible/
class Solution:
def maxDistance(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
q = deque()
vis = set()
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
q.append((i, j, 0))
vis.add((i, j))
ans = -1
while q:
i, j, k = q.popleft()
if grid[i][j] == 0:
ans = max(ans, k)
for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
if 0 <= ni < m and 0 <= nj < n and (ni, nj) not in vis:
q.append((ni, nj, k + 1))
vis.add((ni, nj))
return ans
https://leetcode.com/problems/minimum-genetic-mutation/
class Solution:
def minMutation(self, start: str, end: str, bank: List[str]) -> int:
q = deque()
q.append((start, 0))
vis = set()
vis.add(start)
bank = set(bank)
if end in vis:
return -1
while q:
s, k = q.popleft()
if s == end:
return k
s = list(s)
for i in range(8):
t = s[i]
for c in {'A', 'C', 'G', 'T'} - {t}:
s[i] = c
ns = ''.join(s)
if ns not in vis and ns in bank:
vis.add(ns)
q.append((ns, k + 1))
s[i] = t
return -1
https://leetcode.com/problems/all-nodes-distance-k-in-binary-tree/
class Solution:
def distanceK(self, root: TreeNode, target: TreeNode, k: int) -> List[int]:
def build(root, p):
par[root] = p
if root.left:
build(root.left, root)
if root.right:
build(root.right, root)
par = defaultdict(TreeNode)
build(root, None)
ans = []
q = deque()
q.append([target, 0])
vis = {target}
while q:
cur, step = q.popleft()
if step == k:
ans.append(cur.val)
continue
if cur.left and cur.left not in vis:
q.append([cur.left, step + 1])
vis.add(cur.left)
if cur.right and cur.right not in vis:
q.append([cur.right, step + 1])
vis.add(cur.right)
if par[cur] and par[cur] not in vis:
q.append([par[cur], step + 1])
vis.add(par[cur])
return ans
https://leetcode.com/problems/snakes-and-ladders/
class Solution:
def snakesAndLadders(self, board: List[List[int]]) -> int:
def pos(x):
r, c = (x - 1) // n, (x - 1) % n
if r % 2 == 1:
c = n - 1 - c
return (n - 1 - r, c)
n = len(board)
q = deque()
q.append([1, 0])
vis = {1}
if board[n - 1][0] == n * n:
return 1
while q:
x, k = q.popleft()
if x == n * n:
return k
for i in range(1, 7):
nx = x + i
ni, nj = pos(nx)
if nx <= n * n:
if board[ni][nj] != -1:
nx = board[ni][nj]
if nx not in vis:
vis.add(nx)
q.append([nx, k + 1])
return -1
https://leetcode.com/problems/web-crawler/
class Solution:
def crawl(self, startUrl: str, htmlParser: 'HtmlParser') -> List[str]:
p = startUrl.find('/', 7)
host = startUrl if p == -1 else startUrl[ : p]
a = [startUrl]
ans = {startUrl}
while a:
b = []
for s in a:
for url in htmlParser.getUrls(s):
if url not in ans and url.startswith(host):
ans.add(url)
b.append(url)
a = b
return list(ans)
https://leetcode.com/problems/water-and-jug-problem/
class Solution:
def canMeasureWater(self, x: int, y: int, t: int) -> bool:
q = deque()
q.append((x, y, 0))
vis = {(x, y)}
while q:
a, b, k = q.popleft()
if a + b == t:
return True
for na, nb in [(x, b), (a, y), (0, b), (a, 0), (min(x, a + b), max(0, a + b - x)), (max(0, a + b - y), min(y, a + b))]:
if (na, nb) not in vis:
q.append((na, nb, k + 1))
vis.add((na, nb))
return False
https://leetcode.com/problems/get-watched-videos-by-your-friends/
class Solution:
def watchedVideosByFriends(self, watchedVideos: List[List[str]], friends: List[List[int]], id: int, level: int) -> List[str]:
ans = Counter()
q = deque()
q.append((id, 0))
vis = {id}
while q:
u, k = q.popleft()
if k == level:
ans += Counter(watchedVideos[u])
continue
for v in friends[u]:
if v not in vis:
vis.add(v)
q.append((v, k + 1))
return [k for k, v in sorted(ans.items(), key = lambda x: (x[1], x[0]))]
https://leetcode.com/problems/shortest-path-with-alternating-colors/
class Solution:
def shortestAlternatingPaths(self, n: int, redEdges: List[List[int]], blueEdges: List[List[int]]) -> List[int]:
red, blue = defaultdict(list), defaultdict(list)
for u, v in redEdges:
red[u].append(v)
for u, v in blueEdges:
blue[u].append(v)
ans = [-1] * n
q = deque()
q.append((0, '', 0))
redVis, blueVis = {0}, {0}
while q:
u, c, k = q.popleft()
if ans[u] == -1 or ans[u] > k:
ans[u] = k
if c != 'r':
for v in red[u]:
if v not in redVis:
q.append((v, 'r', k + 1))
redVis.add(v)
if c != 'b':
for v in blue[u]:
if v not in blueVis:
q.append((v, 'b', k + 1))
blueVis.add(v)
return ans
https://leetcode.com/problems/open-the-lock/
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
vis = set(deadends)
if '0000' in vis:
return -1
q = deque()
q.append(('0000', 0))
vis.add('0000')
while q:
s, k = q.popleft()
if s == target:
return k
for d in [-1, 1]:
s = list(s)
for i in range(4):
t = s[i]
s[i] = str((int(s[i]) + d) % 10)
ns = ''.join(s)
if ns not in vis:
vis.add(ns)
q.append((ns, k + 1))
s[i] = t
return -1
https://leetcode.com/problems/stepping-numbers/
class Solution:
def countSteppingNumbers(self, low: int, high: int) -> List[int]:
ans = []
if low == 0:
ans.append(0)
q = deque()
for i in range(1, min(10, high + 1)):
q.append(i)
while q:
u = q.popleft()
if u > high:
break
if u >= low:
ans.append(u)
if u % 10 - 1 >= 0:
q.append(u * 10 + u % 10 - 1)
if u % 10 + 1 <= 9:
q.append(u * 10 + u % 10 + 1)
return ans
https://leetcode.com/problems/numbers-with-same-consecutive-differences/
class Solution:
def numsSameConsecDiff(self, n: int, k: int) -> List[int]:
ans = []
a = [_ for _ in range(1, 10)]
while a:
b = []
for x in a:
if len(str(x)) == n:
ans.append(x)
continue
if k == 0:
a.append(x * 10 + x % 10)
else:
if x % 10 - k >= 0:
a.append(x * 10 + x % 10 - k)
if x % 10 + k <= 9:
a.append(x * 10 + x % 10 + k)
a = b
return ans
https://leetcode.com/problems/minimum-jumps-to-reach-home/
class Solution:
def minimumJumps(self, forbidden: List[int], a: int, b: int, x: int) -> int:
q = deque()
q.append((0, 1, 0))
vis = {(0, 1)}
for v in forbidden:
vis.add((v, 0))
vis.add((v, 1))
while q:
p, back, k = q.popleft()
if p == x:
return k
if p + a <= 6005 and (p + a, 1) not in vis:
q.append((p + a, 1, k + 1))
vis.add((p + a, 1))
if back and p - b >= 0 and (p - b, 0) not in vis:
q.append((p - b, 0, k + 1))
vis.add((p - b, 0))
return -1