问题
给定一个二维数组,nm维度和一个K2的位置数组,1表示砖,0表示空,用炮弹去打砖,打中砖会打碎来变为空,并且和它连着的砖也会落下来,问每发炮打落几块砖,返回每个位置的最佳结果值。
思想
并查集来做,通过设置父子书数组记录谁是谁的父节点将各个位置建立关联,每打一发炮弹就重置天花板砖数,然后查看是否是顶点位置如果是则返回差值,如果不是则继续下一位置。
并查集需要参数:
N:行
M:列
CellingAll:有多少块砖连到天花板上
Grid:原始矩阵,值会变
cellingSet:boolean矩阵true表示该位置是头节点,为天花板集合,false不是天花板集合。
FatherMap:每个位置他的头节点是谁(每个位置进行编号)
SizeMap:每个头节点集合大小
Stack:用来辅助查找父节点
代码
public class Code04_BricksFallingWhenHit {
public static int[] hitBricks(int[][]gird,int[][] hits) {
int N = hits.length;
for(int i = 0;i<N;i++) {
if(gird[hits[i][0]][hits[i][1]] == 1) {
gird[hits[i][0]][hits[i][1]] = 2;
}
}
int[] ans = new int[N];
FindUnion findUnion = new FindUnion(gird);
for(int i = N-1;i>=0;i--) {
if(gird[hits[i][0]][hits[i][1]] == 2) {
ans[i] = findUnion.finger(hits[i][0], hits[i][1]);
}
}
return ans;
}
public static class FindUnion{
private int N;
private int M;
private int cellingAll;
private int[] fatherMap;
private int[] sizeMap;
private int[] stack;
private boolean[] isFather;
private int[][] grid;
public FindUnion(int[][] matrix) {
initSpace(matrix);
inintConnect();
}
private void initSpace(int[][] matrix) {
grid = matrix;
N = grid.length;
M = grid[0].length;
int all = N * M;
fatherMap = new int[all];
sizeMap = new int[all];
stack = new int[all];
isFather = new boolean[all];
for(int row = 0;row<N;row++) {
for(int col = 0;col<M;col++) {
int index = row * M + col;
if(row == 0) {
fatherMap[index] = index;
sizeMap[index] = 1;
isFather[index] = true;
}
}
}
}
private void inintConnect() {
for(int row = 0;row<N;row++) {
for(int col = 0;col<M;col++) {
union(row,col,row+1,col);
union(row,col,row-1,col);
union(row,col,row,col+1);
union(row,col,row,col-1);
}
}
}
private void union(int r1,int c1,int r2,int c2) {
if(isVaild(r1,c1)&&isVaild(r2,c2)) {
int father1 = find(r1,c1);
int father2 = find(r2,c2);
if(father1!=father2) {
int size1 = sizeMap[father1];
int size2 = sizeMap[father2];
boolean status1 = isFather[father1];
boolean status2 = isFather[father2];
if(size1<size2) {
fatherMap[father1] = father2;
sizeMap[father2] = size1 + size2;
if(status1^status2) {
isFather[father2] = true;
cellingAll += status1? size2:size1;
}
}else {
fatherMap[father2] = father1;
sizeMap[father1] = size1 + size2;
if(status1^status2) {
isFather[father1] = true;
cellingAll += status1? size2:size1;
}
}
}
}
}
private int find(int row,int col) {
int index = row * M + col;
int stacksize = 0;
while(index!=fatherMap[index]) {
stack[stacksize++] = index;
index = fatherMap[index];
}
if(stacksize!=0) {
fatherMap[stack[--stacksize]] = index;
}
return index;
}
private boolean isVaild(int r1,int c1) {
return (r1>=0&&r1<N)&&(c1>=0&&c1<M)&&grid[r1][c1] == 1;
}
public int finger(int row,int col) {
grid[row][col] = 1;
int cur = row * M + col;
if(row == 0 ) {
cellingAll = 0;
isFather[cur] = true;
}
fatherMap[cur] = cur;
sizeMap[cur] = 1;
int pre = cellingAll;
union(row,col,row+1,col);
union(row,col,row-1,col);
union(row,col,row,col+1);
union(row,col,row,col-1);
int now = cellingAll;
if(row == 0) {
return now - pre;
}else {
return now == pre?0:now -pre -1;
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}