【Coursera】编程题 Percolation - Algorithms Part1 Week1

拿满分的难点在于尽量减少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) {

    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值