你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。
示例:
输入:
[
[0,2,1,0],
[0,1,0,1],
[1,1,0,1],
[0,1,0,1]
]
输出: [1,2,4]
class Solution { public int[] pondSizes(int[][] land) { UnionfindLinkNode u = new UnionfindLinkNode(land.length, land[0].length, land); for (int i = 0; i < land.length; i++) { for (int j = 0; j < land[i].length; j++) { int cur = land[i][j]; if (cur == 0) { //左边 if (j > 0 && land[i][j- 1] == 0) { u.union(i, j, i, j - 1); } //上边 if (i > 0 && land[i - 1][j] == 0) { u.union(i, j, i - 1, j); } //上斜边1 if (j > 0 && i > 0 && land[i -1][j- 1] == 0) { u.union(i, j, i-1, j - 1); } //上斜边2 if (j < land[i].length -1 && i > 0 && land[i-1][j + 1] == 0) { u.union(i, j, i-1, j + 1); } } } } return u.find(0); } } class UnionfindLinkNode { private Node[][] nodes; private int size; private int num; private int rowSize; private int colSize; public UnionfindLinkNode(int rowSize, int colSize,int[][] arr) { nodes = new Node[rowSize][colSize]; for (int i = 0; i < rowSize; i++) { for (int j = 0; j < colSize; j++) { nodes[i][j] = new Node(arr[i][j], 1); } } this.size = rowSize * colSize; this.num = this.size; this.rowSize = rowSize; this.colSize = colSize; } public int[] find(int val) { Set<Node> list = new HashSet<>(); for (int i = 0; i < rowSize; i++) { for (int j = 0; j < colSize; j++) { Node node = nodes[i][j]; if (node.first.x == val) { list.add(node.first); } } } int[] arr = new int[list.size()]; int i = 0; Iterator<Node> it = list.iterator(); while (it.hasNext()) { arr[i++] = it.next().cnt; } Arrays.sort(arr); return arr; } public boolean union(int x, int y, int x1, int y1) { if (x1 < 0 || y1 < 0 || x1 >= rowSize || y1 >= colSize) { return false; } Node nodeX = nodes[x][y]; Node nodeY = nodes[x1][y1]; //代表节点 Node firstX = nodeX.first; Node firstY = nodeY.first; if (firstX == firstY) { return false; } firstX.setCnt(firstX.getCnt() + firstY.getCnt()); //尾节点 Node tailX = firstX.pre; Node tailY = firstY.pre; tailX.next = firstY; firstY.pre = tailX; tailY.next = firstX; firstX.pre = tailY; //更新y链表的代表节点 Node start = firstY; while (start != tailY) { start.first = firstX; start = start.next; } tailY.first = firstX; size--; System.out.println(x + ":" + y + ":" + size); return true; } public boolean isSameSet(int x, int y, int x1, int y1) { return nodes[x][y].first == nodes[x1][y1].first; } public int size() { return size; } } class Node { //上一个节点 Node pre = this; //下一个节点 Node next = this; //代表节点 Node first = this; //值 int x; //节点数 int cnt; public Node(int x, int cnt) { this.x = x; this.cnt = cnt; } public int getCnt() { return cnt; } public void setCnt(int cnt) { this.cnt = cnt; } }