Detect whether a directed graph given as an edge list contains a cycle
Company: Oracle
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
You are given a directed graph with `n` nodes labeled `0` to `n - 1` and a list of directed edges. Return whether the graph contains at least one directed cycle.
### Function Signature
```python
def has_cycle(n: int, edges: list[list[int]]) -> bool:
```
`edges[i] = [u, v]` is a directed edge from node `u` to node `v`.
### Rules
- A directed cycle is a path of one or more edges that follows edge directions and returns to the node it started from.
- A self-loop `[u, u]` is a cycle of length one.
- The same edge may appear more than once. Two copies of the edge from `u` to `v` do not form a cycle by themselves.
- The graph may be disconnected, and some nodes may have no edges at all.
- Return `True` if at least one directed cycle exists anywhere in the graph, otherwise `False`.
### Constraints
- `1 <= n <= 10^5`
- `0 <= len(edges) <= 2 * 10^5`
- `0 <= u <= n - 1` and `0 <= v <= n - 1` for every edge `[u, v]`
### Examples
**Example 1**
```text
Input: n = 4, edges = [[0, 1], [0, 2], [1, 3], [2, 3]]
Output: False
```
Node 3 can be reached from node 0 along two paths, `0 -> 1 -> 3` and `0 -> 2 -> 3`, but no path ever leads back to a node it has already passed through.
**Example 2**
```text
Input: n = 5, edges = [[4, 0], [0, 1], [1, 2], [2, 3], [3, 1]]
Output: True
```
The edges `1 -> 2`, `2 -> 3` and `3 -> 1` form a cycle.
**Example 3**
```text
Input: n = 2, edges = [[0, 1], [1, 1]]
Output: True
```
The self-loop on node 1 is a cycle of length one.
Overview: A coding question that asks whether a directed graph, given as a node count and a list of edges, contains at least one directed cycle. It tests graph traversal on large inputs and careful handling of self-loops, duplicate edges, converging paths and disconnected components.
Read the full Oracle Software Engineer interview experience this question came from
You are given a directed graph with `n` nodes labeled `0` to `n - 1` and a list `edges`, where `edges[i] = [u, v]` is a directed edge from node `u` to node `v`. Return whether the graph contains at least one directed cycle.
### Rules
- A directed cycle is a path of one or more edges that follows edge directions and returns to the node it started from.
- A self-loop `[u, u]` is a cycle of length one.
- The same edge may appear more than once. Two copies of the edge from `u` to `v` do not form a cycle by themselves.
- The graph may be disconnected, and some nodes may have no edges at all.
- Return `True` if at least one directed cycle exists anywhere in the graph, otherwise `False` (`true` / `false` in JavaScript, Java and C++).
### Constraints
- `1 <= n <= 10^5`
- `0 <= len(edges) <= 2 * 10^5`
- Every `edges[i]` is a pair `[u, v]` with `0 <= u <= n - 1` and `0 <= v <= n - 1`
- All values fit in a 32-bit signed integer; no value exceeds `2^31 - 1`.
### Example 1
```text
Input: n = 4, edges = [[0, 1], [0, 2], [1, 3], [2, 3]]
Output: False
```
Node 3 can be reached from node 0 along two paths, `0 -> 1 -> 3` and `0 -> 2 -> 3`, but no path ever leads back to a node it has already passed through.
### Example 2
```text
Input: n = 5, edges = [[4, 0], [0, 1], [1, 2], [2, 3], [3, 1]]
Output: True
```
The edges `1 -> 2`, `2 -> 3` and `3 -> 1` form a cycle.
Constraints
- 1 <= n <= 10^5
- 0 <= len(edges) <= 2 * 10^5
- edges[i] = [u, v] with 0 <= u <= n - 1 and 0 <= v <= n - 1
- Self-loops and repeated identical edges may appear; the graph may be disconnected and nodes may have no edges
- All values fit in a 32-bit signed integer (none exceeds 2^31 - 1)
Examples
Input: (4, [[0, 1], [0, 2], [1, 3], [2, 3]])
Expected Output: False
Explanation: Source Example 1: diamond DAG; node 3 is reached along two paths but no path returns to its start.
Input: (5, [[4, 0], [0, 1], [1, 2], [2, 3], [3, 1]])
Expected Output: True
Explanation: Source Example 2: edges 1 -> 2, 2 -> 3, 3 -> 1 form a cycle reached from the source chain 4 -> 0 -> 1.
Hints
- Reaching the same node along two different paths, like node 3 in Example 1, is not a cycle. A cycle needs a path that comes back to the node where it started.
- The graph may be disconnected, so a cycle can sit in a part of the graph that node 0 cannot reach. Make sure every node is considered.
- A self-loop [u, u] counts as a cycle, but repeated copies of the same edge u -> v do not. Your handling of edges must keep these two cases apart.