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; } }