• <Graph> Topological + Undirected Graph 310 Union Find 261 + 323 + (hard)305


    310. Minimum Height Trees

     queue:  degree为1的顶点

    degree[ i ] : 和 i 顶点关联的边数。 

    先添加整个图,然后BFS删除每一层degree为1的节点。

    class Solution {
        public List<Integer> findMinHeightTrees(int n, int[][] edges) {
            List<Integer> result = new ArrayList<>();
            if(n == 1){
                result.add(0);
                return result;
            }
            int[] degree = new int[n];
            Map<Integer, List<Integer>> map = new HashMap<>();
            for(int i = 0; i < n; i++) map.put(i, new ArrayList<>());
            for(int[] pair : edges){
                map.get(pair[0]).add(pair[1]);
                map.get(pair[1]).add(pair[0]); 
                degree[pair[0]]++;
                degree[pair[1]]++;
            }
            
            Queue<Integer> queue = new LinkedList<>();
            for(int i = 0; i < n; i++){
                if(degree[i] == 1) queue.add(i);
            }
            
            while(!queue.isEmpty()){
                List<Integer> list = new ArrayList<>();
                int size = queue.size();
                for(int i = 0; i < size; i++){
                    int cur = queue.poll();
                    list.add(cur);
                    for(int nei : map.get(cur)){
                        degree[nei]--;
                        if(degree[nei] == 1) queue.add(nei);
                    }
                }
                result = list;
            }
            return result;
        }
    }

    261. Graph Valid Tree

    Union Find: 并查集,这种方法对于解决连通图的问题很有效,思想是我们遍历节点,如果两个节点相连,我们将其roots值连上,这样可以帮助我们找到环,我们初始化roots数组为-1,然后对于一个pair的两个节点分别调用find函数,得到的值如果相同的话,则说明环存在,返回false,不同的话,我们将其roots值union上

    class Solution {
        public boolean validTree(int n, int[][] edges) {
            int[] nums = new int[n];
            Arrays.fill(nums, -1);
            
            for(int i = 0; i < edges.length; i++){
                int x = find(nums, edges[i][0]);
                int y = find(nums, edges[i][1]);
            
                if(x == y) return false;       
                nums[x] = y;
            }
            return edges.length == n - 1;
        }
        
        private int find(int[] nums, int i){
            if(nums[i] == -1) return i;
            return find(nums, nums[i]);
        }
    }

    323. Number of Connected Components in an Undirected Graph

     寻找无向图里的连通量。用并查集的方法。

    建立一个root数组,下标和节点值相同,此时root[i]表示节点i属于group i,我们初始化了n个部分 (res = n),假设开始的时候每个节点都属于一个单独的区间,然后我们开始遍历所有的edge,对于一条边的两个点,他们起始时在root中的值不相同,这时候我们我们将结果减1,表示少了一个区间,然后更新其中一个节点的root值,使两个节点的root值相同,那么这样我们就能把连通区间的所有节点的root值都标记成相同的值,不同连通区间的root值不相同,这样也能找出连通区间的个数。

     1) x != y  :两个点原来是不相通的,现在连接了,把后一个点的root更新与x相同。

     2) x == y : 两个点是相通的,res不需要减一。

    class Solution {
        public int countComponents(int n, int[][] edges) {
            int res = n;
            int[] root = new int[n]; 
            for(int i = 0; i < n; i++){
                root[i] = i;
            }
            for(int[] edge : edges){
                int x = find(root, edge[0]);
                int y = find(root, edge[1]);
                if(x != y){
                    res--;
                    root[y] = x;
                }
            }
            return res;
        }
        
        private int find(int[] root, int i){
            while(root[i] != i) i = root[i];
            return i;
        }
    }

    305. Number of Islands II

    用int nb = n * x + y转为一维数组

    class Solution {
        int[][] dirs ={{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
        
        public List<Integer> numIslands2(int m, int n, int[][] positions) {
            List<Integer> res = new ArrayList<>();
            if(m <= 0 || n <= 0) return res;
            
            int count = 0;
            int[] roots = new int[m * n];
            Arrays.fill(roots, -1);
            
            for(int[] p : positions){
                int root = n * p[0] + p[1];
                if(roots[root] != -1){
                    res.add(count);
                    continue;
                }
                roots[root] = root;
                count++;
                
                for(int[] dir : dirs){
                    int x = p[0] + dir[0];
                    int y = p[1] + dir[1];
                    int nb = n * x + y;
                    if(x < 0 || x >= m || y < 0 || y >= n || roots[nb] == -1) continue;
                    
                    int rootSurr = find(roots, nb);
                    if(root != rootSurr){
                        roots[root] = rootSurr;
                        root = rootSurr;
                        count--;
                    }
                }
            res.add(count);  
            }
            return res;
        }
        
        public int find(int[] roots, int i){
            while(i != roots[i]) i = roots[i];
            return i;
        }
    }
  • 相关阅读:
    HQL语句中类的别名语法以及作用?
    C#面向对象
    c#异步编程一
    c#接口
    c#Socket通信基本使用
    c#FTP基本使用
    c#XML的基本使用
    c#装箱与拆箱
    c#数组与集合
    c#中for与foreach的使用
  • 原文地址:https://www.cnblogs.com/Afei-1123/p/12049612.html
Copyright © 2020-2023  润新知