diagram-projectGraph

Notes and typical questions for String related problems

Notes

  • Most DFS questions can also be resolved by BFS.

  • BFS is useful when finding the shortest path to a position.

  • Find Shortest Path

    • Unweighted graph: BFS

    • Non-negative weighted graph: Dijkstra's algorithm, which relies on the greedy algorithm

Typical Questions

DFS

  • Notes

    • 2 Implementation approach: Stack and Recursion

  • 🌟 LC 841. Keys and Rooms

    • Stack Answerarrow-up-right.

      • TC: O(N+E)O(N+E), where N is the number of rooms, and E is the total number of keys.

      • SC: O(N)O(N), store stack and visited array.

    • Recursion Answerarrow-up-right

      • TC: O(N+E)O(N+E), where N is the number of rooms, and E is the total number of keys.

      • SC: O(N)O(N), store visited array. In the worst case, the recursion depth can go up to NN

  • 🌟 LC 547. Number of Provinces

  • 🔴 LC 1466. Reorder Routes to Make All Paths Lead to the City Zero

    • Key points

      • Input has n node, n-1 edges, and only 1 edge between 2 nodes. Therefore there must be no circle and it looks like a tree.

      • To resolve this issue, we can first double the edge between every 2 nodes by adding 1 "artificial edge" so every node is reachable by an "artificial" or "original" edge. Then we can do DFS from node '0' and count the number of "original edges" during traversal. See detailed explanation in LC editorial.

    • Optimal Answerarrow-up-right

      • TC: O(n)O(n), both adjacency map initialization and DFS are O(n)O(n)

      • SC: O(n)O(n).

        • Adjacency list takes O(n)O(n) space. It has nn keys and 2(n1)2*(n-1) values

        • The recursion call stack used by DFS can have no more than n elements in the worst-case scenario. It would take up to O(n)O(n) space in that case.

  • LC 399. Evaluate Division

    • Resolved by myself but it's easy to make some mistakes during implementation and I polished the answer a bit based on the editorial

    • Optimal Answerarrow-up-right.

      • TC: O(MN)O(M*N), where NN is the number of input equations and MM is the number of queries.

      • SC: O(N)O(N)

  • LC 130. Surrounded Regions

    • I made it the first time I met this problem!

    • Both BFS (multi-source) and DFS can solve this problem.

    • Optimal Answerarrow-up-right. TC: O(mn)O(m*n), SC: O(mn)O(m*n). In DFS, the recursion stack depth is at most m × n because DFS only explores one path at a time. It does not push all four directions simultaneously; instead, it follows a single direction as deep as possible before backtracking. In a grid, this single path can visit every cell once, leading to a maximum recursion depth of O(m*n).

  • LC 133. Clone Graph

    • Both BFS and DFS can solve this problem

    • DFS Answerarrow-up-right. NN is the number of nodes (vertices) and MM is the number of edges. TC: O(M+N)O(M+N), SC: O(N)O(N)

  • LC 79. Word Search

    • Optimal Answerarrow-up-right.

      • Let board size = M×N, word length = L

      • TC: O(MN43L1)O(M*N*4*3^{L-1}), SC: O(L)O(L)

    • Follow-up question ideas

      • Letter frequency check (fail fast): If word needs 3 'A's but board only has 2, return false immediately. Often eliminates impossible cases instantly.

      • Reverse the word (start from rarer end): DFS branching depends heavily on how many starting cells match the first letter. If the first char is very common, you start DFS from many cells.

BFS

Classic BFS

  • Notes

    • Use Queue to implement it.

    • For multi-source BFS questions, we need to offer all sources into the queue at first.

    • Mark node visited: Most BFS questions can reuse the existing input grid to mark visited nodes without introducing a new data structure.

    • BFS Complexity

      • Space Complexity: By the way, normally for BFS, the main space complexity lies in the process rather than the initialization. For instance, for a BFS traversal in a tree, at any given moment, the queue would hold no more than 2 levels of tree nodes. Therefore, the space complexity of BFS traversal in a tree would depend on the width of the input tree.

      • Time Complexity: In a typical BFS search, the time complexity is O(V+E)O(V+E) where VV is the number of nodes and EE is the number of edges. There are nn nodes and at most n2n^2 edges in this problem.

  • 🌟 LC 1926. Nearest Exit from Entrance in Maze

    • I feel like my solution is a little bit better than the editorial. I iterate a fixed queue size each time to control steps.

    • Optimal Answerarrow-up-right

      • TC: O(MN)O(M*N), where MM is the row length of the input, and NN is the column length of the input

      • SC: O(M+N)O(M+N), where MM is the row length of the input, and NN is the column length of the input

        The largest queue I could think of is when you start in the exact middle of a square and add all of the outermost nodes. Example: 2, 2, 2, 2, 2 2, 1, 1, 1, 2 2, 1, 0, 1, 2 2, 1, 1, 1, 2 2, 2, 2, 2, 2 You can see in the above example that the max size of the queue will be when you have all of the 2 distance nodes added. The space complexity would be 2m + 2n = O(m+n)

  • 🌟 LC 994. Rotting Oranges

    • Optimal Answerarrow-up-right.

      • TC: O(MN)O(M*N), where MM is the row length of the input, and NN is the column length of the input

      • SC: O(MN)O(M*N), where MM is the row length of the input, and NN is the column length of the input. In the worst case, the grid is filled with rotten oranges. As a result, the queue would be initialized with all the cells in the grid.

  • 🌟 LC 200. Number of Islands

    • Both DFS and BFS can work.

    • Optimal Answerarrow-up-right. TC: O(mn)O(m*n), SC: O(min(m,n))O(min(m,n)).

      • For SC, please go through some examples (3*3 grid, 3*4 grid) then you can get it. Or 1 image below is worth 1000 lines. It's because this is single-source BFS. Multi-source BFS space complexity is still m*n.

  • 🟠 LC 959. Regions Cut By Slashes

    • The most important part is that you need to be able to think of converting this problem into LC 200.

    • Optimal Answerarrow-up-right. TC: O(n2)O(n^2), SC: O(n2)O(n^2)

  • LC 2101. Detonate the Maximum Bombs

  • 🔴 LC 773. Sliding Puzzle

    • It's tough to come up with this solution. Use BFS because we want to find the smallest moves.

    • Optimal Answerarrow-up-right. TC: O(mn)!O(m*n)!, SC: O(mn)!O(m*n)!

  • LC 909. Snakes and Ladders

    • Spend a lot of time on understanding description and writing code...

    • Optimal Answerarrow-up-right. TC: O(n2)O(n^2), SC: O(n2)O(n^2)

  • LC 433. Minimum Genetic Mutation

  • LC 127. Word Ladder

    • Similar to the above LC433. No need to create an extra visited set becausethe dictionary set can be reused as a visited set.

    • Optimal Answerarrow-up-right. Let NN be the number of words in the dictionary and LL be the length of words. TC: O(NL2)O(N*L^2), SC: O(N)O(N)

  • LC 317. Shortest Distance from All Buildings

    • I came up with an answer by myself by missing 1 optimization that I don't need to maintain both visited and globalVisited matrix.

    • Optimal Answerarrow-up-right. TC: O(m2n2)O(m^2*n^2), SC: O(mn)O(m*n)

  • LC 827. Making A Large Island

🧩 Dijkstra's Algorithm

  • Notes

    • PriorityQueue<int[]> minHeap + Map<Integer, int[]> adj + int[] visited

    • Reach Nodes

      • A node is considered "visited" only when it is polled from the heap.

      • Update the visited array at this point.

      • The first time a node is polled, the corresponding time/path is guaranteed to be the shortest.

    • Need to do dedup using the visited array in 2 places because multiple edges to a specific node can be pushed into the heap before visiting that node.

    • visited array serves 2 purposes

      • Check if a node is visited

      • Store the shortest time to reach each node

  • 🌟 🔴 LC 743. Network Delay Time

    • Optimal Answerarrow-up-right.

      • TC: O(ElogV)O(E*log{V}), it is actually O(ElogE)O(E*log{E}), but O(ElogE)=O(ElogV(V1))=O(ElogV2)=O(E2logV)O(E*log{E}) = O(E*log{V*(V-1)}) = O(E*log{V^2}) = O(E*2*log{V})

      • SC: O(E+V)O(E+V)

  • 🌟 🟠 LC 2812. Find the Safest Path in a Grid

    • This implementation is simpler than classic Dijkstra's Algorithm because the weight is on the vertex itself instead of on the edge -> for all previous paths (without this node) to get to this node, they all add the same weight (this node weight).

      • In this case, we can mark the node as visited in the neighbors' exploration logic directly as it must be the optimal path here (if the path without this node is optimal, the path with this node is also optimal among all paths to this node).

    • Answerarrow-up-right. TC: O(lognn2)O(log{n}*n^2), SC: O(n2)O(n^2)

      • Looks like there is a better solution with TC O(n2)O(n^2)

  • 🟠 LC 787. Cheapest Flights Within K Stops

    • This deduplication is only done in one place when polling a node from the heap. This is because we also use k to limit that dedup logic.

    • Dijkstra's Answerarrow-up-right. TC: O(N+EKlog(EK))O(N+E*K*log(E*K)), SC: O(N+EK)O(N+E*K)

🧩 Disjoint Set / Union-Find Set

  • Notes

    • The code for the disjoint set is highly modularized. Understand and memorize the implementation of “disjoint set with path compression and union by rank”.

    • Time Complexity

      • NN is the number of vertices in the graph. α\alpha refers to the Inverse Ackermann function. In practice, we assume it's a constant. In other words, O(α(n))O(\alpha(n)) is regarded as O(1)O(1) on average.

      • Constructor: O(n)O(n)

      • int find(int x): O(α(n))O(\alpha(n))

      • union(int x, int y): O(α(n))O(\alpha(n))

      • boolean connext(int x, int y): O(α(n))O(\alpha(n))

    • Space Complexity: O(n)O(n)

  • 🌟 LC 1101. The Earliest Moment When Everyone Become Friends

    • Optimal Answerarrow-up-right

      • Let MM be the number of logs, NN be the number of friends

        • TC: O(MlogM+Mα(N))O(M*log{M}+M*\alpha(N))

        • SC: O(N+M)O(N+M)

  • 🟠 LC 305. Number of Islands II

🧩 Topological Sort

  • LC 207. Course Schedule

    • This is actually a classic topological problem but can also be resolved by DFS to check the cycle.

    • 🟠 Approach 1 using DFS. Optimal Answerarrow-up-right. We need to maintain 2 visited lists (path & global) to save time by skipping nodes in the previous DFS. Otherwise, it will be TLE (okay, I get TLE again in 2nd time...)

      • Let nn be the number of courses and mm be the size of prerequisites. TC: O(m+n)O(m+n). SC: O(m+n)O(m+n)

    • 👍 Approach 2 using Topological sort. Optimal Answerarrow-up-right. TC: O(m+n)O(m+n). SC: O(m+n)O(m+n)

  • 🌟 LC 210. Course Schedule II

  • LC 2115. Find All Possible Recipes from Given Supplies

  • LC 1136. Parallel Courses

  • 🔴 LC 269. Alien Dictionary

    • The two main blockers to address this question

      • Realize this is related to topological sort.

      • How to build the adj map.

    • Optimal Answerarrow-up-right.

      • Let NN be the total number of strings in the input list.

      • Let CC be the total length of all the words in the input list, added together.

      • Let UU be the total number of unique letters in the alien alphabet. While this is limited to 2626 in the question description, we'll still look at how it would impact the complexity if it was not limited (as this could potentially be a follow-up question).

      • TC: O(C+U+min(U2,N1))O(C+U+min(U^2, N-1))O(C)O(C)

      • SC: O(U+min(U2,N1))O(U+min(U^2, N-1))

  • 🔴 LC 2603. Collect Coins in a Tree

    • Its idea is difficult to come up with, and it's hard to implement the idea.

    • When removing coin leaves, the pruning must be done layer by layer (in rounds), not by immediately removing a leaf and its parent while iterating. Removing a parent as soon as it becomes a leaf is based on a transient state created mid-iteration. This can cause cascading deletions, effectively pruning more than the intended number of layers (2) and removing nodes that should remain. See the picture as an example.

    • Optimal Answerarrow-up-right. Let nn be the number of nodes. TC: O(n)O(n), SC: O(n)O(n)

🧩 Bipartite

  • Notes

    • Hungarian Algorithm: Finding a maximum bipartite matching

      • Key points: Create a new visitedGirls set for each boy instead of using a global set.

        • This ensures that each DFS attempt starts fresh and independently checks all possible paths.

        • If a global set were used, previously visited girls would remain marked across different DFS calls, preventing valid matchings from being explored.

  • 🌟 🟠 LC 1820. Maximum Number of Accepted Invitations

    • It is exactly the "Max Bipartite Matching algorithm"

    • Optimal Answerarrow-up-right.

      • Let M M be the number of boys and NN be the number of girls

      • TC: O(MN2)O(M*N^2)

        • This is estimated by (calling DFS M times) * (iterate through every girl (N in total)) * (Calling DFS and it iterates through every girl (N in total))

      • SC: O(N)O(N)

Last updated