Algorithm I assignment Percolation
这道题来自Algorithms 4th的公开课,是week1的assignment。该题主要是对并查集的应用,点击:参考
看过lecture后,想到解决这道题的思路并不难,不过想要拿到满分着实费功夫...累积花费了5个小时才AC。
在实现代码过程中遇到了以下问题:
- 时间复杂度超了,因为在实现percolates()时,采用了遍历的方式检查:所以在grid的上下两端虚拟两个site。默认其和第一行和最后一行是连通的。
- 由于采用了虚拟的site,引入了新问题:backwash。即isFull()会把下图右侧的也认为是full状态。解决办法:采取的解决办法是用两个并查集,多出来那个并查集只有上部的虚拟site,没有下部的。
- percolation.java和percolationStat.java的空间复杂度都超了。percolation:开始没有使用两个并查集时没超,用了结果就超了,不过超的不多。这里面有一个int[][],int是4个字节,改成了boolean[][],结果就不超了。对于percolationStat,超内存超了600多倍...猜测是我把一个临时变量定义成了全局的,所以在多次测试时,gc没有回收掉。后来每次使用后,将这个临时的引用赋值为null就好了。实际上,不应该使用全局,既然是临时变量,只需要在更小的作用域里声明就行了。
代码:
1 import edu.princeton.cs.algs4.WeightedQuickUnionUF; 2 3 public class Percolation { 4 private WeightedQuickUnionUF UF; 5 private WeightedQuickUnionUF UF1; 6 private boolean[][] grid; 7 private int N; 8 9 // create N-by-N grid, with all sites blocked 10 public Percolation(int N) { 11 if (N < 1) { 12 throw new java.lang.IllegalArgumentException(); 13 } 14 this.N = N; 15 grid = new boolean[N + 1][N + 1]; 16 UF = new WeightedQuickUnionUF(N * N + 2); 17 UF1 = new WeightedQuickUnionUF(N * N + 1); 18 } 19 20 // open site (row i, column j) if it is not open already 21 public void open(int i, int j) { 22 if (i < 1 || j < 1 || i > N || j > N) { 23 throw new java.lang.IndexOutOfBoundsException(); 24 } 25 if (!grid[i][j]) { 26 if (i == 1) { 27 UF.union(0, j); 28 UF1.union(0, j); 29 } 30 if (i == N) { 31 UF.union(N * N + 1, (i - 1) * N + j); 32 } 33 grid[i][j] = true; 34 // judge whether this is full or not 35 // left 36 if (j > 1) { 37 if (isOpen(i, j - 1)) { 38 UF.union((i - 1) * N + j, (i - 1) * N + j - 1); 39 UF1.union((i - 1) * N + j, (i - 1) * N + j - 1); 40 } 41 } 42 // right 43 if (j < N) { 44 if (isOpen(i, j + 1)) { 45 UF.union((i - 1) * N + j, (i - 1) * N + j + 1); 46 UF1.union((i - 1) * N + j, (i - 1) * N + j + 1); 47 } 48 } 49 // up 50 if (i > 1) { 51 if (isOpen(i - 1, j)) { 52 UF.union((i - 1) * N + j, (i - 1 - 1) * N + j); 53 UF1.union((i - 1) * N + j, (i - 1 - 1) * N + j); 54 } 55 } 56 // down 57 if (i < N) { 58 if (isOpen(i + 1, j)) { 59 UF.union((i - 1) * N + j, (i + 1 - 1) * N + j); 60 UF1.union((i - 1) * N + j, (i + 1 - 1) * N + j); 61 } 62 } 63 } 64 } 65 66 // is site (row i, column j) open? 67 public boolean isOpen(int i, int j) { 68 if (i < 1 || j < 1 || i > N || j > N) { 69 throw new java.lang.IndexOutOfBoundsException(); 70 } 71 if (grid[i][j]) { 72 return true; 73 } 74 return false; 75 } 76 77 // is site (row i, column j) full? 78 public boolean isFull(int i, int j) { 79 if (i < 1 || j < 1 || i > N || j > N) { 80 throw new java.lang.IndexOutOfBoundsException(); 81 } 82 if (grid[i][j]) 83 if (UF1.connected(0, (i - 1) * N + j)) { 84 return true; 85 } 86 return false; 87 } 88 89 // does the system percolate? 90 public boolean percolates() { 91 return UF.connected(0, N * N + 1); 92 } 93 94 // test client (optional) 95 public static void main(String[] args) { 96 } 97 }
1 import edu.princeton.cs.algs4.StdIn; 2 import edu.princeton.cs.algs4.StdRandom; 3 import edu.princeton.cs.algs4.StdStats; 4 5 public class PercolationStats { 6 private double[] results; 7 private double mean; 8 private double stddev; 9 private double confidenceLo; 10 private double confidenceHi; 11 private Percolation perc; 12 13 // perform T independent experiments on an N-by-N grid 14 public PercolationStats(int N, int T) { 15 if (N < 1 || T < 1) { 16 throw new java.lang.IllegalArgumentException(); 17 } 18 results = new double[T]; 19 for (int i = 0; i < T; i++) { 20 perc = new Percolation(N); 21 int result = 0; 22 while (!perc.percolates()) { 23 int x = StdRandom.uniform(N) + 1; 24 int y = StdRandom.uniform(N) + 1; 25 while (perc.isOpen(x, y)) { 26 x = StdRandom.uniform(N) + 1; 27 y = StdRandom.uniform(N) + 1; 28 } 29 perc.open(x, y); 30 result++; 31 } 32 perc = null; 33 results[i] = result / (N * N * 1.0); 34 } 35 mean = StdStats.mean(results); 36 stddev = StdStats.stddev(results); 37 confidenceLo = mean - 1.96 * stddev / Math.sqrt(T); 38 confidenceHi = mean + 1.96 * stddev / Math.sqrt(T); 39 } 40 41 // sample mean of percolation threshold 42 public double mean() { 43 return mean; 44 } 45 46 // sample standard deviation of percolation threshold 47 public double stddev() { 48 return stddev; 49 } 50 51 // low endpoint of 95% confidence interval 52 public double confidenceLo() { 53 return confidenceLo; 54 } 55 56 // high endpoint of 95% confidence interval 57 public double confidenceHi() { 58 return confidenceHi; 59 } 60 61 // test client (described below) 62 public static void main(String[] args) { 63 int N = StdIn.readInt(); 64 int T = StdIn.readInt(); 65 PercolationStats unittest = new PercolationStats(N, T); 66 System.out.println("mean = " + unittest.mean()); 67 System.out.println("stddev = " + unittest.stddev()); 68 System.out.println("95% confidence interval = " 69 + unittest.confidenceLo() + ", " + unittest.confidenceHi()); 70 71 } 72 }
下面是提交结果 :)