261J. Graph Valid Tree

https://leetcode.com/problems/graph-valid-tree/

Method Best

一个无向图是不是树有两个要素: 一是只能有一部分,就是全部连通。 二是不能有环。

检测无环的方式是什么呢? 如果做DFS,到下一层,发现该节点已经被访问过了,由于是 无向图,除非这个节点就是自己的上一层,否则说明该无向图 必然有环。

class Solution {
    // Graph是Tree,首先要只有一个部分,其次不能有环。
    // count 数有几个部分
    // hasCycle 判断是否有环
    private int count;
    private boolean hasCycle;
    private boolean[] visited;
    
    public boolean validTree(int n, int[][] edges) {
        // Initialize Global Variables
        this.count = 0;
        this.visited = new boolean[n];
        this.hasCycle = false;
        // Initialize Graph
        List<Integer>[] adj = new ArrayList[n];
        for(int i = 0; i < n; i++) adj[i] = new ArrayList<>();
        for(int[] pairs : edges){
            adj[pairs[0]].add(pairs[1]);
            adj[pairs[1]].add(pairs[0]);
        }
        // DFS
        for(int i = 0; i < n; i++){
            if(!this.visited[i]){
                dfs(adj,i,i);
                count++;
            }
        }
        // Graph是Tree,首先要只有一个部分,其次不能有环。
        return (count < 2) && (!hasCycle) ;
    }
    
    private void dfs(List<Integer>[] adj, int cur, int last ){
        visited[cur] = true;
        for(int next : adj[cur]){
            if(!visited[next]){
                dfs(adj, next, cur);
            }else if(next != last){
                this.hasCycle = true;
            }
        }
    } 
}

202309 写了一个 early return 多一点的

class Solution {
    boolean hasCycle;
    boolean[] marked;
    public boolean validTree(int n, int[][] edges) {
        this.hasCycle = false;
        this.marked = new boolean[n];
        ArrayList<Integer>[] adj = new ArrayList[n];
        for (int i = 0; i < n; i++) adj[i] = new ArrayList<>();
        for (int[] edge : edges) {
            adj[edge[0]].add(edge[1]);
            adj[edge[1]].add(edge[0]);
        }
        int island = 0;
        for (int i = 0; i < n; i++) {
            if (hasCycle || island > 1) return false;
            if (marked[i]) continue;
            island++;
            dfs(adj, i, i);
        }
        return !hasCycle && island == 1;
    }

    private void dfs(ArrayList<Integer>[] adj, int cur, int prev) {
        if (hasCycle) return;
        marked[cur] = true;
        for (int next : adj[cur]) {
            if (marked[next]) {
                if (next != prev) {
                    this.hasCycle = true;
                    return;
                }
                continue;
            }
            dfs(adj, next, cur);
        }
    }
}

这个题用 bfs 的 indegrees (kahn's algorithm) 也可以写,但是比较麻烦的地方是需要判断是不是所有的点都是联通的。

Last updated

Was this helpful?