拿满分的难点在于尽量减少for - loop 的次数,尤其是在需要频繁调用的方法里。
如果只建立一个UnionFind对象,得在 percolates() 里头用for循环,时间上划不来。
而建两个UF对象就可以解决底部虚拟节点和 isFull() 冲突的问题,多用一点点内存。反正内存可以花钱买,时间不行。。。
这个题目里输入的row、col居然是从1开始的,简直反人类。
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
public class Percolation {
private int numOfOpen = 0, n;
private WeightedQuickUnionUF uF, uF2;
private boolean[] blocked;
public Percolation(int n) {
if (n <= 0)
throw new IllegalArgumentException("Invalid n or trials.");
this.n = n;
uF = new WeightedQuickUnionUF(n * n + 2); //两个虚拟节点top = n * n ;down = n * n + 1
uF2 = new WeightedQuickUnionUF(n * n + 1); //优化isFull专用,不设立底部结点。
blocked = new boolean[n * n];
for (int i = 0; i < blocked.length; i++) {
blocked[i] = true;
}
for (int i = 0; i < n; i++) { //连接top点和第一行
uF.union(i, n * n);
uF2.union(i, n * n);
}
for (int i = n * (n - 1); i < n * n; i++) { //连接down点和最后一行
uF.union(i, n * n + 1);
}
}
public void open(int row, int col) {
if (row > n || row <= 0 || col > n || col <= 0)
throw new IndexOutOfBoundsException("row/col index is out of bounds");
row--;
col--;
int index = row * n + col;
if (blocked[index]) {
blocked[index] = false;
numOfOpen++;
}
else
return;
if (index - n >= 0) {
if (!blocked[index - n]) {
uF.union(index, index - n);
uF2.union(index, index - n);
}
}
if (index + n < n * n) {
if (!blocked[index + n]) {
uF.union(index, index + n);
uF2.union(index, index + n);
}
}
if ((index + 1) / n == index / n) {
if (!blocked[index + 1]) {
uF.union(index, index + 1);
uF2.union(index, index + 1);
}
}
if ((index - 1) / n == index / n && index - 1 >= 0) {
if (!blocked[index - 1]) {
uF.union(index, index - 1);
uF2.union(index, index - 1);
}
}
}
public boolean isOpen(int row, int col) {
if (row > n || row <= 0 || col > n || col <= 0)
throw new IndexOutOfBoundsException("row/col index is out of bounds");
row--;
col--;
int index = row * n + col;
return !blocked[index];
}
public boolean isFull(int row, int col) {
if (row > n || row <= 0 || col > n || col <= 0)
throw new IndexOutOfBoundsException("row/col index is out of bounds");
row--;
col--;
int index = row * n + col;
if (uF2.connected(index, n * n) && isOpen(row + 1, col + 1))
return true;
else
return false;
}
public int numberOfOpenSites() {
return numOfOpen;
}
public boolean percolates() {
if (n != 1)
return uF.connected(n * n, n * n + 1);
else {
return isOpen(1, 1);
}
}
public static void main(String[] args) {
}
}