问题描述:
Given a n,m which means the row and column of the 2D matrix and an array of pair A( size k). Originally, the 2D matrix is all 0 which means there is only sea in the matrix. The list pair has k operator and each operator has two integer A[i].x, A[i].y means that you can change the grid matrix[A[i].x][A[i].y] from sea to island. Return how many island are there in the matrix after each operator.
解题思路:
可以使用union-find(并查集)来解决这道问题。
在本题中提供的为二维坐标,但并查集中多用一维数组,我们可以通过使用 idx = x * m + y 来唯一确定二维数组中的一个位置的一维表示方法。其中m为列数。
再插入每一个位置的时候,检查上下左右是否为岛屿,如果是,则需要合并岛屿。
代码:
** * Definition for a point. * class Point { * int x; * int y; * Point() { x = 0; y = 0; } * Point(int a, int b) { x = a; y = b; } * } */ public class Solution { /** * @param n: An integer * @param m: An integer * @param operators: an array of point * @return: an integer array */ public List<Integer> numIslands2(int n, int m, Point[] operators) { // write your code here ArrayList<Integer> ret = new ArrayList<Integer>(); if(operators == null || operators.length == 0) return ret; int count = 0; int[] parent = new int[n*m]; int[][] direction = {{-1,0}, {1, 0},{0,-1},{0,1}}; for(int i = 0; i < n*m; i++){ parent[i] = -1; } for(int i = 0; i < operators.length; i++){ Point curPoint = operators[i]; int curID = calID(curPoint.x, curPoint.y, m); if(parent[curID] != -1){ ret.add(count); continue; } count++; parent[curID] = curID; //check surrounds if(curPoint.x - 1 >= 0){ int adjID = calID(curPoint.x-1, curPoint.y, m); if(parent[adjID] != -1){ count = union(parent, curID, adjID, count); } } if(curPoint.y - 1 >= 0){ int adjID = calID(curPoint.x, curPoint.y-1, m); if(parent[adjID] != -1){ count = union(parent, curID, adjID, count); } } if(curPoint.x + 1 < n){ int adjID = calID(curPoint.x + 1, curPoint.y, m); if(parent[adjID] != -1){ count = union(parent, curID, adjID, count); } } if(curPoint.y + 1 < m){ int adjID = calID(curPoint.x, curPoint.y + 1, m); if(parent[adjID] != -1){ count = union(parent, curID, adjID, count); } } ret.add(count); } return ret; } private int calID(int i, int j, int row){ return i*row + j; } private int find(int[] parent, int a){ if(parent[a] == a){ return a; } return parent[a] = find(parent, parent[a]); } private int union(int[] parent, int a, int b, int count){ int rootA = find(parent, a); int rootB = find(parent, b); if(rootA != rootB) { parent[rootB] = rootA; count--; } return count; } }
其中,check surround中可以通过二维数组direction来进行检查
int[][] direction = {{-1,0}, {1, 0},{0,-1},{0,1}};
检查代码为:
for(int[] d : direction){ int adjX = curPoint.x + d[0]; int adjY = curPoint.y + d[1]; int adjID = calID(adjX, adjY, m); if( adjX >= 0 && adjX < n &&adjY >= 0 && adjY < m && parent[adjID] != -1){ count = union(parent, curID, adjID, count); } }
粗心出现过的bug _(:з」∠)_:
- 在计算唯一id:calID时,将x*m+y 算成了x*n+y, 导致了id不唯一 TAT
- 在周围检测时,在检查0的时候,用了<0而非<=0,导致边缘无法跳入代码块
做题用的时间不多,但是debug反而用了很久。。以后一定要多多小心,仔细答题!