From 196be85defe98bd340b24e934b763bdb42812ede Mon Sep 17 00:00:00 2001 From: Leo <582717189@qq.com> Date: Tue, 29 Dec 2020 11:24:43 +0800 Subject: [PATCH] class15 --- src/leo/class09_13/LowestAncestor.java | 110 +++++++++- src/leo/class09_15/FriendCircles.java | 166 ++++++++++----- src/leo/class09_15/NumberOfIslands.java | 230 ++++++++++++++++++++- src/leo/class09_15/NumberOfIslandsII.java | 237 ++++++++++++++++++++++ 4 files changed, 682 insertions(+), 61 deletions(-) create mode 100644 src/leo/class09_15/NumberOfIslandsII.java diff --git a/src/leo/class09_13/LowestAncestor.java b/src/leo/class09_13/LowestAncestor.java index 0519b19..d04abd1 100644 --- a/src/leo/class09_13/LowestAncestor.java +++ b/src/leo/class09_13/LowestAncestor.java @@ -7,24 +7,25 @@ package leo.class09_13; * @Description * 给定一棵二叉树的头节点head,和另外两个节点a和b。 * 返回a和b的最低公共祖先 + * https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/ */ public class LowestAncestor { static class Code { - static Node lowestAncestor(Node head, Node a, Node b) { + static TreeNode lowestCommonAncestor(TreeNode head, TreeNode a, TreeNode b) { return process(head, a, b).ans; } - static Info process(Node node, Node a, Node b) { + static Info process(TreeNode node, TreeNode a, TreeNode b) { if (node == null) { return new Info(null, false, false); } - Info left = process(node, a, b); - Info right = process(node, a, b); + Info left = process(node.left, a, b); + Info right = process(node.right, a, b); boolean findA = left.findA || right.findA || a == node; boolean findB = left.findB || right.findB || b == node; - Node ans = null; + TreeNode ans = null; if (left.ans != null) { ans = left.ans; } @@ -40,15 +41,110 @@ public class LowestAncestor { } static class Info { - Node ans; + TreeNode ans; boolean findA; boolean findB; - public Info(Node ans, boolean findA, boolean findB) { + public Info(TreeNode ans, boolean findA, boolean findB) { this.ans = ans; this.findA = findA; this.findB = findB; } } } + + class Code1 { + + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + return process(root, p, q).ans; + } + + public Info process(TreeNode node,TreeNode a,TreeNode b) { + if (node == null) { + return new Info(null, false, false); + } + Info left = process(node.left, a, b); + Info right = process(node.right, a, b); + boolean findA = left.findA || right.findA || node == a; + boolean findB = left.findB || right.findB || node == b; + TreeNode ans = null; + if (left.ans != null) { + ans = left.ans; + } + if (right.ans != null) { + ans = right.ans; + } + if (ans == null) { + if (findA && findB) { + ans = node; + } + } + return new Info(ans, findA, findB); + } + + class Info { + TreeNode ans; + boolean findA; + boolean findB; + + public Info(TreeNode ans, boolean findA, boolean findB) { + this.ans = ans; + this.findA = findA; + this.findB = findB; + } + } + + + } + + class Code2 { + public TreeNode lowestCommonAncestor(TreeNode head, TreeNode a, TreeNode b) { + + return process(head, a, b).ans; + } + + public Info process(TreeNode node, TreeNode a, TreeNode b) { + if (node == null) { + return new Info(null, false, false); + } + Info left = process(node.left, a, b); + Info right = process(node.right, a, b); + boolean findA = left.findA || right.findA || node == a; + boolean findB = left.findB || right.findB || node == b; + TreeNode ans = null; + if (left.ans != null) { + ans = left.ans; + } + if (right.ans != null) { + ans = right.ans; + } + if (findA && findB) { + if (ans == null) { + ans = node; + } + } + return new Info(ans, findA, findB); + } + + + class Info{ + TreeNode ans; + boolean findA; + boolean findB; + + public Info(TreeNode ans, boolean a, boolean b) { + + this.ans = ans; + this.findA = a; + this.findB = b; + } + } + } + + public class TreeNode { + int val; + TreeNode left; + TreeNode right; + TreeNode(int x) { val = x; } + } } diff --git a/src/leo/class09_15/FriendCircles.java b/src/leo/class09_15/FriendCircles.java index b5862c6..844ec77 100644 --- a/src/leo/class09_15/FriendCircles.java +++ b/src/leo/class09_15/FriendCircles.java @@ -9,71 +9,137 @@ package leo.class09_15; */ public class FriendCircles { - public int findCircleNum(int[][] M) { - int n = M.length; - UnionFind unionFind = new UnionFind(n); - for (int i = 0; i < n; i++) { - for (int j = i + 1; j < n; j++) { - if (M[i][j] == 1) { - unionFind.union(i, j); + class Code1 { + public int findCircleNum(int[][] M) { + int n = M.length; + UnionFind unionFind = new UnionFind(n); + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + if (M[i][j] == 1) { + unionFind.union(i, j); + } } - } + } + return unionFind.sets; } - return unionFind.sets; - } - public class UnionFind { - // i的父级节点是parent[i] - int[] parent; - // i的集合大小为size[i] - int[] size; - //辅助结构 - int[] help; - //一共多少个集合 - int sets; - public UnionFind(int n) { - - parent = new int[n]; - size = new int[n]; - help = new int[n]; - sets = n; + public class UnionFind { + // i的父级节点是parent[i] + int[] parent; + // i的集合大小为size[i] + int[] size; + //辅助结构 + int[] help; + //一共多少个集合 + int sets; + public UnionFind(int n) { + + parent = new int[n]; + size = new int[n]; + help = new int[n]; + sets = n; + for (int i = 0; i < n; i++) { + parent[i] = i; + size[i] = 1; + } + } + + public int find(int i) { + int h = 0; + while (i != parent[i]) { + help[h++] = i; + i = parent[i]; + } + for (h--; h >= 0; h--) { + parent[help[h]] = i; + } + return i; + } + + public void union(int i, int j) { + int iF = find(i); + int jF = find(j); + if (jF != iF) { + int iSize = size[iF]; + int jSize = size[jF]; + int big = iSize >= jSize ? iF : jF; + int small = big == iF ? jF : iF; + parent[small] = big; + size[big] = jSize + iSize; + sets--; + } + } + + public int sets() { + return sets; + } + } + } + class Code2 { + public int findCircleNum(int[][] M) { + int n = M.length; + UnionFind unionFind = new UnionFind(n); for (int i = 0; i < n; i++) { - parent[i] = i; - size[i] = 1; + for (int j = i + 1; j < n; j++) { + if (M[i][j] == 1) { + unionFind.union(i, j); + } + } } + return unionFind.sets; } - public int find(int i) { - int h = 0; - while (i != parent[i]) { - help[h++] = i; - i = parent[i]; + public class UnionFind { + int[] parent; + int[] size; + int[] help; + int sets; + + public UnionFind(int n) { + parent = new int[n]; + size = new int[n]; + help = new int[n]; + sets = n; + for (int i = 0; i < n; i++) { + parent[i] = i; + size[i] = 1; + } } - for (h--; h >= 0; h--) { - parent[help[h]] = i; + public int find(int i) { + int h = 0; + while (i != parent[i]) { + help[h++] = i; + i = parent[i]; + } + for (h--; h >= 0; h--) { + parent[help[h]] = i; + } + return i; } - return i; - } + public void union(int i, int j) { + int iF = find(i); + int jF = find(j); + if (iF != jF) { + int iSize = size[iF]; + int jSize = size[jF]; + int big = iSize >= jSize ? iF : jF; + int small = big == iF ? jF : iF; + parent[small] = big; + size[big] = iSize + jSize; + sets--; + } - public void union(int i, int j) { - int iF = find(i); - int jF = find(j); - if (jF != iF) { - int iSize = size[iF]; - int jSize = size[jF]; - int big = iSize >= jSize ? iF : jF; - int small = big == iF ? jF : iF; - parent[small] = big; - size[big] = jSize + iSize; - sets--; } - } - public int sets() { - return sets; + public int sets() { + return sets; + } + } + } + } diff --git a/src/leo/class09_15/NumberOfIslands.java b/src/leo/class09_15/NumberOfIslands.java index 594e97e..3dac7cc 100644 --- a/src/leo/class09_15/NumberOfIslands.java +++ b/src/leo/class09_15/NumberOfIslands.java @@ -1,9 +1,6 @@ package leo.class09_15; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Stack; +import java.util.*; /** * @author Leo @@ -41,6 +38,31 @@ public class NumberOfIslands { infect(grid, r, c+1); } } + static class C1 { + public static int numIslands (char[][] grid) { + int count = 0; + for (int i = 0; i < grid.length; i++) { + for (int j = 0; j < grid[0].length; j++) { + if (grid[i][j] == '1') { + count++; + infect(grid, i, j); + } + } + } + return count; + } + + private static void infect(char[][] grid, int i, int j) { + if (i < 0 || j == grid[0].length || j < 0 || i == grid.length || grid[i][j] != '1') { + return; + } + grid[i][j] = '2'; + infect(grid, i + 1, j); + infect(grid, i - 1, j); + infect(grid, i, j + 1); + infect(grid, i, j - 1); + } + } } @@ -147,6 +169,114 @@ public class NumberOfIslands { } } + static class C1 { + public int numIslands(char[][] grid) { + List list = new ArrayList<>(); + int r = grid.length; + int c = grid[0].length; + Dot[][] dot = new Dot[r][c]; + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + if (grid[i][j] == '1') { + dot[i][j] = new Dot(); + list.add(dot[i][j]); + } + } + } + UnionFind u = new UnionFind(list); + //上左依次合并 + //第一行每一列与第二行每一列合并 + for (int i = 1; i < grid.length; i++) { + if (grid[i - 1][0] == '1' && grid[i][0] == '1') { + u.union(dot[i - 1][0], dot[i][0]); + } + } + //每行的第一列与第二列合并 + for (int i = 1; i < grid[0].length; i++) { + if (grid[0][i - 1] == '1' && grid[0][i] == '1') { + u.union(dot[0][i - 1], dot[0][i]); + } + } + + for (int i = 1; i < r; i++) { + for (int j = 1; j < c; j++) { + if (grid[i][j] == '1') { + if (grid[i - 1][j] == '1') { + u.union(dot[i][j], dot[i - 1][j]); + } + if (grid[i][j - 1] == '1') { + u.union(dot[i][j], dot[i][j - 1]); + } + } + } + + } + return u.sets(); + } + + class UnionFind{ + HashMap> nodes; + HashMap,Node> parent; + HashMap,Integer> size; + + public UnionFind(List list) { + nodes = new HashMap<>(); + parent = new HashMap<>(); + size = new HashMap<>(); + for (int i = 0; i < list.size(); i++) { + Node node = new Node(list.get(i)); + nodes.put(list.get(i), node); + parent.put(node, node); + size.put(node, 1); + } + } + + public Node find(V v) { + Stack stack = new Stack<>(); + Node cur = nodes.get(v); + while (cur != parent.get(cur)) { + stack.push(cur); + cur = parent.get(cur); + } + while (!stack.isEmpty()) { + parent.put(stack.pop(), cur); + } + return cur; + } + + public void union(V a, V b) { + Node aF = find(a); + Node bF = find(b); + if (aF == bF) { + return; + } + int aSize = size.get(aF); + int bSize = size.get(bF); + Node big = aSize >= bSize ? aF : bF; + Node small = big == aF ? bF : aF; + parent.put(small, big); + size.put(big, aSize + bSize); + size.remove(small); + } + + public int sets() { + return size.size(); + } + } + + class Dot { + + } + + class Node { + V value ; + public Node(V v) { + this.value = v; + } + } + + } + } @@ -248,9 +378,101 @@ public class NumberOfIslands { return r * col + c; } } + } + class C1 { + public int numIslands(char[][] grid) { + UnionFind u = new UnionFind(grid); + int row = grid.length; + int col = grid[0].length; + for (int i = 1; i < row; i++) { + if (grid[i - 1][0] == '1' && grid[i][0] == '1') { + u.union(i - 1, 0, i, 0); + } + } + for (int i = 1; i < col; i++) { + if (grid[0][i - 1] == '1' && grid[0][i] == '1') { + u.union(0, i - 1, 0, i); + } + } + for (int i = 1; i < row; i++) { + for (int j = 1; j < col; j++) { + if (grid[i][j] == '1') { + if (grid[i - 1][j] == '1') { + u.union(i, j, i - 1, j); + } + if (grid[i][j - 1] == '1') { + u.union(i, j, i, j - 1); + } + } + } + } + return u.sets(); + } + class UnionFind { + int[] parent; + int[] size; + int[] help; + int col; + int set; + + public UnionFind(char[][] grid) { + int row = grid.length; + col = grid[0].length; + int n = row * col; + parent = new int[n]; + size = new int[n]; + help = new int[n]; + set = 0; + for (int i = 0; i < row; i++) { + for (int j = 0; j < col; j++) { + if (grid[i][j] == '1') { + int x = getIndex(i, j); + parent[x] = x; + size[x] = 1; + set++; + } + } + } + + } + public int find(int i) { + int hi = 0; + while (i != parent[i]) { + help[hi++] = i; + i = parent[i]; + } + for (hi--; hi >= 0; hi--) { + parent[help[hi]] = i; + } + return i; + } + public void union(int i1, int j1, int i2, int j2) { + int a = getIndex(i1, j1); + int b = getIndex(i2, j2); + int aF = find(a); + int bF = find(b); + if (aF == bF) { + return; + } + int aSize = size[aF]; + int bSize = size[bF]; + int big = aSize >= bSize ? aF : bF; + int small = big == aF ? bF : aF; + parent[small] = big; + size[big] = aSize + bSize; + set--; + } + + public int sets() { + return set; + } + public int getIndex(int i, int j) { + return i * col + j; + } + } } } diff --git a/src/leo/class09_15/NumberOfIslandsII.java b/src/leo/class09_15/NumberOfIslandsII.java new file mode 100644 index 0000000..8061e41 --- /dev/null +++ b/src/leo/class09_15/NumberOfIslandsII.java @@ -0,0 +1,237 @@ +package leo.class09_15; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Leo + * @ClassName NumberOfIslandsII + * @DATE 2020/12/25 3:14 下午 + * @Description 305 + * 测试链接:https://leetcode.com/problems/number-of-islands-ii/ + */ +public class NumberOfIslandsII { + + static class C { + public static List numIslands(int m, int n, int[][] positions) { + UnionFind1 uf = new UnionFind1(m, n); + List ans = new ArrayList<>(); + for (int[] position : positions) { + ans.add(uf.connect(position[0], position[1])); + } + return ans; + } + + public static class UnionFind1 { + private int[] parent; + private int[] size; + private int[] help; + private final int row; + private final int col; + private int sets; + + public UnionFind1(int m, int n) { + row = m; + col = n; + sets = 0; + int len = row * col; + parent = new int[len]; + size = new int[len]; + help = new int[len]; + } + + private int index(int r, int c) { + return r * col + c; + } + + private int find(int i) { + int hi = 0; + while (i != parent[i]) { + help[hi++] = i; + i = parent[i]; + } + for (hi--; hi >= 0; hi--) { + parent[help[hi]] = i; + } + return i; + } + + private void union(int r1, int c1, int r2, int c2) { + if (r1 < 0 || r1 == row || r2 < 0 || r2 == row || c1 < 0 || c1 == col || c2 < 0 || c2 == col) { + return; + } + int i1 = index(r1, c1); + int i2 = index(r2, c2); + if (size[i1] == 0 || size[i2] == 0) { + return; + } + int f1 = find(i1); + int f2 = find(i2); + if (f1 != f2) { + if (size[f1] >= size[f2]) { + size[f1] += size[f2]; + parent[f2] = f1; + } else { + size[f2] += size[f1]; + parent[f1] = f2; + } + sets--; + } + } + + public int connect(int r, int c) { + int index = index(r, c); + if (size[index] == 0) { + parent[index] = index; + size[index] = 1; + sets++; + union(r - 1, c, r, c); + union(r + 1, c, r, c); + union(r, c - 1, r, c); + union(r, c + 1, r, c); + } + return sets; + } + + } + } + + + static class C1 { + public static List numIslands(int m,int n,int[][] positions) { + UnionFind unionFind = new UnionFind(m, n); + List list = new ArrayList<>(); + for (int[] position : positions) { + list.add(unionFind.connect(position[0], position[1])); + } + return list; + } + + static class UnionFind { + int[] parent; + int[] size; + int[] help; + int col; + int row; + int set; + + public UnionFind(int m, int n) { + row = m; + col = n; + int len = row * col; + parent = new int[len]; + size = new int[len]; + help = new int[len]; + set = 0; + } + + public int find(int i) { + int hi = 0; + while (i != parent[i]) { + help[hi++] = i; + i = parent[i]; + } + for (hi--; hi >= 0; hi--) { + parent[help[hi]] = i; + } + return i; + } + public int index(int r, int c) { + return r * col + c; + } + public void union(int r1, int c1, int r2, int c2) { + if (r1 < 0 || r1 == row || r2 < 0 || r2 == row || c1 < 0 || c1 == col || c2 < 0 || c2 == col) { + return; + } + int i1 = index(r1, c1); + int i2 = index(r2, c2); + if (size[i1] == 0 || size[i2] == 0) { + return; + } + int aF = find(i1); + int bF = find(i2); + if (aF == bF) { + return; + } + int aSize = size[aF]; + int bSize = size[bF]; + int big = aSize >= bSize ? aF : bF; + int small = big == aF ? bF : aF; + parent[small] = big; + size[big] = aSize + bSize; + set--; + } + + public int connect(int r, int c) { + int i = index(r, c); + if (size[i] == 0) { + size[i] = 1; + parent[i] = i; + set++; + union(r - 1, c, r, c); + union(r + 1, c, r, c); + union(r, c - 1, r, c); + union(r, c + 1, r, c); + } + return set; + } + } + + } + + + public static void main(String[] args){ + + int mMax = 20; + int nMax = 20; + + int test = 100; + System.out.println("start"); + for (int i = 0; i < test; i++) { + int m = (int) ((Math.random() * mMax) + 1); + int n = (int) ((Math.random() * nMax) + 1); + int[][] positions = randomPositions(m, n); + List list = C.numIslands(m, n, positions); + List list1 = C1.numIslands(m, n, positions); + if (!isListEqual(list, list1)) { + System.out.println(list.toString()); + System.out.println(list1.toString()); + break; + + } + } + System.out.println("end"); + + } + + public static boolean isListEqual(List l0, List l1){ + if (l0 == l1) + return true; + if (l0 == null && l1 == null) + return true; + if (l0 == null || l1 == null) + return false; + if (l0.size() != l1.size()) + return false; + for (Object o : l0) { + if (!l1.contains(o)) + return false; + } + for (Object o : l1) { + if (!l0.contains(o)) + return false; + } + return true; + } + + private static int[][] randomPositions(int m, int n) { + int size = (int) (Math.random() * m * n) + 1; + int[][] positions = new int[size][2]; + for (int i = 0; i < positions.length; i++) { + positions[i][0] = (int) (Math.random() * m); + positions[i][1] = (int) (Math.random() * n); + } + return positions; + + } +}