c++讓人迷惑的動靜態連編
阿新 • • 發佈:2020-12-14
朋友圈 題目 解析
class Solution { class UF { private int count; private int parent[]; //它的父節點 private int size[]; //以自己為根節點的樹有多少節點 public UF(int n) { this.count = n; parent = new int[n]; size = new int[n]; //初始化的時候自己的父節點指向自己 for(int i = 0; i < n; i++) { parent[i] = i; size[i] = 1; } } //找到x的根節點 private int find(int x) { while (x != parent[x]) { //路徑壓縮,畫個圖就明白了。就是和自己的父親做兄弟。 parent[x] = parent[parent[x]]; x= parent[x]; } return x; } //連線 public void union(int p, int q) { //找到各自的根節點。 int rootP = find(p); //你看,每次find的時候都進行了路徑壓縮。 int rootQ = find(q); if (rootP == rootQ) return; //把小的樹接到大的樹上面 if(size[rootQ] > size[rootP]) { parent[rootP] = rootQ; size[rootQ] += size[rootP]; } else { parent[rootQ] = rootP; size[rootP] += size[rootQ]; } count--; } public boolean connect(int p, int q) { return find(p) == find(q); } public int count() { return count; } } public int findCircleNum(int[][] M) { int N = M.length; UF uf = new UF(N); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (M[i][j] == 1) { uf.union(i, j); } } } return uf.count(); } }
深度優先
class Solution { public int findCircleNum(int[][] M) { int N = M.length, count = 0; boolean[] V = new boolean[N]; for (int i = 0; i < N; i++) { if (!V[i]) { count++; dfs(V, M, i); } } return count; } private void dfs(boolean[] V, int[][]M, int i) { for (int j = 0; j < M.length; j++) { if (M[i][j] == 1 && !V[j]) { V[j] = true; dfs(V, M, j); } } } }
廣度優先
class Solution { public int findCircleNum(int[][] M) { int N = M.length, count = 0; Queue<Integer> queue = new LinkedList<>(); boolean[] V = new boolean[N]; for (int i = 0; i < N; i++) { if (!V[i]) { queue.offer(i); count++; while (!queue.isEmpty()){ int k = queue.poll(); V[k] = true; for (int j = 0; j < N; j++) { if (M[k][j] == 1 && !V[j]) { queue.offer(j); } } } } } return count; } }