码迷,mamicode.com
首页 > 其他好文 > 详细

Princeton-Algorithms-Part1-Week1-Percolation

时间:2017-12-29 19:59:53      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:sigma   this   only   ide   color   ica   magic   htm   ace   

技术分享图片

技术分享图片

Assignment specification: https://www.coursera.org/learn/algorithms-part1/programming/Lhp5z/percolation

Idea1: Virtual top and bottom sites

技术分享图片

 1 import edu.princeton.cs.algs4.WeightedQuickUnionUF;
 2 
 3 public class Percolation {
 4     
 5     private boolean[][] sites;
 6     private int numOfOpenSites;
 7     private final WeightedQuickUnionUF uf;
 8     private final int n;
 9     private final int top;
10     private final int bottom;
11         
12     public Percolation(int n) {
13         if (n <= 0) throw new IllegalArgumentException();
14         sites = new boolean[n][n];
15         numOfOpenSites = 0;
16         uf = new WeightedQuickUnionUF(n * n + 2);
17         this.n = n;
18         this.top = n * n;
19         this.bottom = n * n + 1;
20         for (int i = 0; i <= n - 1; i++) uf.union(top, i);
21         for (int i = n * n - n; i <= n * n - 1; i++) uf.union(bottom, i);
22     }
23     
24     public void open(int row, int col) {
25         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
26         if (isOpen(row, col)) return;
27         sites[row - 1][col - 1] = true;
28         numOfOpenSites++;
29         
30         int ufIndex = convertMatrixIndexToUFIndex(row, col);
31         if (row > 1 && isOpen(row - 1, col)) {
32             uf.union(ufIndex, convertMatrixIndexToUFIndex(row - 1, col));
33         }
34         if (row < n && isOpen(row + 1, col)) {
35             uf.union(ufIndex, convertMatrixIndexToUFIndex(row + 1, col));
36         }
37         if (col > 1 && isOpen(row, col - 1)) {
38             uf.union(ufIndex, convertMatrixIndexToUFIndex(row, col - 1));
39         }
40         if (col < n && isOpen(row, col + 1)) {
41             uf.union(ufIndex, convertMatrixIndexToUFIndex(row, col + 1));
42         }
43     }
44     
45     private int convertMatrixIndexToUFIndex(int row, int col) {
46         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
47         return (row - 1) * n + col - 1;
48     }
49     
50     public boolean isOpen(int row, int col) {
51         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
52         return sites[row - 1][col - 1];
53     }
54     
55     public boolean isFull(int row, int col) {
56         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
57         return isOpen(row, col) 
58             && uf.connected(top, convertMatrixIndexToUFIndex(row, col));
59     }
60     
61     public int numberOfOpenSites() {
62         return numOfOpenSites;
63     }
64     
65     public boolean percolates() {
66         return uf.connected(top, bottom);
67     }
68     
69     private boolean isInvalidInput(int row, int col) {
70         return row <= 0 || row > n || col <= 0 || col > n;
71     }
72 }

Running time:

Weighted Union-Find: connected log(n^2); find log(n^2); union log(n^2);

Percolation: open log(n^2); isOpen O(1); isFull log(n^2); numberOfOpenSites O(1); percolates log(n^2);

Memory:

Weighted Union-Find: O(n^2)

Percolation: O(n^2)

Problem:

1. Failed on cases when n equals 1.

2. Backwash problem:

技术分享图片

Idea2: Separate virtual top from virtual bottom

Use two Union-Find, topUF(with virtual top site) and bottomUF(with virtual bottom site). The sites percolates when a open site both connect with virtual top and virtual bottom. A site is full when it connects the virtual top.

 1 import edu.princeton.cs.algs4.WeightedQuickUnionUF;
 2 
 3 public class Percolation {
 4     
 5     private boolean[][] sites;
 6     private int numOfOpenSites;
 7     private final WeightedQuickUnionUF topUF;
 8     private final WeightedQuickUnionUF bottomUF;
 9     private final int n;
10     private final int top;
11     private final int bottom;
12     private boolean isPercolate;
13         
14     public Percolation(int n) {
15         if (n <= 0) throw new IllegalArgumentException();
16         sites = new boolean[n][n];
17         numOfOpenSites = 0;
18         topUF = new WeightedQuickUnionUF(n * n + 1);
19         bottomUF = new WeightedQuickUnionUF(n * n + 1);
20         this.n = n;
21         this.top = n * n;
22         this.bottom = n * n;
23         this.isPercolate = false;
24         for (int i = 0; i <= n - 1; i++) topUF.union(top, i);
25         for (int i = n * n - n; i <= n * n - 1; i++) bottomUF.union(bottom, i);
26     }
27     
28     public void open(int row, int col) {
29         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
30         if (isOpen(row, col)) return;
31         sites[row - 1][col - 1] = true;
32         numOfOpenSites++;
33         
34         int ufIndex = convertMatrixIndexToUFIndex(row, col);
35         if (row > 1 && isOpen(row - 1, col)) {
36             int up = convertMatrixIndexToUFIndex(row - 1, col);
37             topUF.union(ufIndex, up);
38             bottomUF.union(ufIndex, up);
39         }
40         if (row < n && isOpen(row + 1, col)) {
41             int down = convertMatrixIndexToUFIndex(row + 1, col);
42             topUF.union(ufIndex, down);
43             bottomUF.union(ufIndex, down);
44         }
45         if (col > 1 && isOpen(row, col - 1)) {
46             int left = convertMatrixIndexToUFIndex(row, col - 1);
47             topUF.union(ufIndex, left);
48             bottomUF.union(ufIndex, left);
49         }
50         if (col < n && isOpen(row, col + 1)) {
51             int right = convertMatrixIndexToUFIndex(row, col + 1);
52             topUF.union(ufIndex, right);
53             bottomUF.union(ufIndex, right);
54         }
55         isPercolate = isPercolate || topUF.connected(ufIndex, top) 
56             && bottomUF.connected(ufIndex, bottom);
57     }
58     
59     private int convertMatrixIndexToUFIndex(int row, int col) {
60         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
61         return (row - 1) * n + col - 1;
62     }
63     
64     public boolean isOpen(int row, int col) {
65         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
66         return sites[row - 1][col - 1];
67     }
68     
69     public boolean isFull(int row, int col) {
70         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
71         return isOpen(row, col) 
72             && topUF.connected(top, convertMatrixIndexToUFIndex(row, col));
73     }
74     
75     public int numberOfOpenSites() {
76         return numOfOpenSites;
77     }
78     
79     public boolean percolates() {
80         return this.isPercolate;
81     }
82     
83     private boolean isInvalidInput(int row, int col) {
84         return row <= 0 || row > n || col <= 0 || col > n;
85     }
86 }

Running time:

Weighted Union-Find: connected log(n^2); find log(n^2); union log(n^2);

Percolation: open log(n^2); isOpen O(1); isFull log(n^2); numberOfOpenSites O(1); percolates log(n^2);

Memory:

Weighted Union-Find: O(n^2)

Percolation: O(n^2)

Trade-off:

Pro: Bug free; Backwash solved;

Con: Use two Union-Find instance;

Idea3: Without virtual top and bottom

Hide information in root. In int[][] sites matrix, 0000 means blocked, 0001 means opened, 0010 means connect to top, 0100 means connect to bottom. Magic happens in open() method. When try to connect the open site with its adjacent four neighbors, the root status of the new combined part is determined by those of its four neighbors. And isPercolate becomes true when the new root status equals 0111 which means both connect to top and bottom. Idea comes from: https://www.sigmainfy.com/blog/avoid-backwash-in-percolation.html

 1 import edu.princeton.cs.algs4.WeightedQuickUnionUF;
 2 
 3 public class Percolation {
 4     
 5     private int[][] sites;
 6     private int numOfOpenSites;
 7     private final WeightedQuickUnionUF uf;
 8     private final int n;
 9     private boolean isPercolate;
10         
11     public Percolation(int n) {
12         if (n <= 0) throw new IllegalArgumentException();
13         sites = new int[n][n];
14         numOfOpenSites = 0;
15         uf = new WeightedQuickUnionUF(n * n);
16         this.n = n;
17         this.isPercolate = false;
18     }
19     
20     public void open(int row, int col) {
21         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
22         if (isOpen(row, col)) return;
23         numOfOpenSites++;
24         
25         int newRootStatus = 1;
26         if (row == 1) newRootStatus = newRootStatus | 2;
27         if (row == n) newRootStatus = newRootStatus | 4;
28         int ufIndex = convertMatrixIndexToUFIndex(row, col);
29         if (row > 1 && isOpen(row - 1, col)) {
30             newRootStatus = newRootStatus | findRootStatus(row - 1, col);
31             uf.union(ufIndex, convertMatrixIndexToUFIndex(row - 1, col));
32         }
33         if (row < n && isOpen(row + 1, col)) {
34             newRootStatus = newRootStatus | findRootStatus(row + 1, col);
35             uf.union(ufIndex, convertMatrixIndexToUFIndex(row + 1, col));
36         }
37         if (col > 1 && isOpen(row, col - 1)) {
38             newRootStatus = newRootStatus | findRootStatus(row, col - 1);
39             uf.union(ufIndex, convertMatrixIndexToUFIndex(row, col - 1));
40         }
41         if (col < n && isOpen(row, col + 1)) {
42             newRootStatus = newRootStatus | findRootStatus(row, col + 1);
43             uf.union(ufIndex, convertMatrixIndexToUFIndex(row, col + 1));
44         }
45         isPercolate = isPercolate || (newRootStatus & 7) == 7;
46         int newRoot = uf.find(ufIndex);
47         sites[newRoot / n][newRoot % n] = newRootStatus;
48     }
49     
50     private int convertMatrixIndexToUFIndex(int row, int col) {
51         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
52         return (row - 1) * n + col - 1;
53     }
54     
55     private int findRootStatus(int row, int col) {
56         int ufIndex = convertMatrixIndexToUFIndex(row, col);
57         int rootIndex = uf.find(ufIndex);
58         return sites[rootIndex / n][rootIndex % n];
59     }
60     
61     public boolean isOpen(int row, int col) {
62         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
63         return (findRootStatus(row, col) & 1) == 1;
64     }
65     
66     public boolean isFull(int row, int col) {
67         if (isInvalidInput(row, col)) throw new IllegalArgumentException();
68         return (findRootStatus(row, col) & 2) == 2;
69     }
70     
71     public int numberOfOpenSites() {
72         return numOfOpenSites;
73     }
74     
75     public boolean percolates() {
76         return this.isPercolate;
77     }
78     
79     private boolean isInvalidInput(int row, int col) {
80         return row <= 0 || row > n || col <= 0 || col > n;
81     }
82 }

Running time:

Weighted Union-Find: connected log(n^2); find log(n^2); union log(n^2);

Percolation: open log(n^2); isOpen log(n^2); isFull log(n^2); numberOfOpenSites O(1); percolates log(n^2);

Memory:

Weighted Union-Find: O(n^2)

Percolation: O(n^2)

Trade-off:

Pro: Bug free; Backwash solved; Use only one Union-Find instance;

Con: A lot of calls to UnionFind.find();

 

.

 

Princeton-Algorithms-Part1-Week1-Percolation

标签:sigma   this   only   ide   color   ica   magic   htm   ace   

原文地址:https://www.cnblogs.com/Kaneki-Ken/p/8144265.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!