Coursera Algorithms Week1 Homework Percolation

这个问题的文档让我学到很多,一个完整的问题规范,自己写程序也要这样分析。
MODEL
PROBLEM
边界 throw exception 情况
(PERCOLATION DATA TYPE)
(MONTE CARLOSIMULATION)
ANALYSIS OF RUNNING TIME AND MEMORY USAGE

最后的检测中也学到很多东西。
1.API一定不能少,这也是工作里最最重要的一条。
2.PMD也要重视:

  • private属性要不要final
  • 变量需lowCase加camelCase
  • 缩进里别用制表符
  • 逗号前面不要空格
//Percolation.java
import edu.princeton.cs.algs4.WeightedQuickUnionUF;

/**
 * Builds a N*N sized WeightedQuickUnionUF grid to mock create a simple percolation system. Initially all
 * nodes in the grid are blocked and must be opened. The grid is considered to percolate when there is a
 * connection from an open node on the top row to an open node on the bottom row.
 *
 * Whether a node is open or not is kept in an array. All connections are done through a WeightedQuickUnionUF object.
 *
 * We have a second WeightedQuickUnionUF object for checking fullness so as to not run into the backwash issue.
 */
public class Percolation {
    private WeightedQuickUnionUF grid;
    private WeightedQuickUnionUF full;
    private int N;
    private int top;
    private int bottom;
    private boolean[] openNodes;

    /**
     * Initialises an N * N WeightedQuickUnionUF object plus two extra nodes for the virtual top and virtual bottom
     * nodes. Creates an internal boolean array to keep track of whether a node is considered open or not.
     *
     * Also initialises a second N * N WeightedQuickUnionUF object plus one extra node as a second collection to check
     * for fullness and avoid the backwash issue.
     *
     * @param N The dimensions of the grid
     */
    public Percolation(int N) {
        if (N <= 0) {
            throw new java.lang.IllegalArgumentException("Woah, N must be greater than zero");
        }

        grid = new WeightedQuickUnionUF(N * N + 2);
        full = new WeightedQuickUnionUF(N * N + 1);

        this.N = N;

        top = getSingleArrayIdx(N, N) + 1;
        bottom = getSingleArrayIdx(N, N) + 2;

        openNodes = new boolean[N * N];
    }

    /**
     * Converts an index for a 0-based array from two grid coordinates which are 1-based. First checks to see if the
     * coordinates are out of bounds.
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    private int getSingleArrayIdx(int i, int j) {
        doOutOfBoundsCheck(i, j);

        return (N * (i - 1) + j) - 1;
    }

    /**
     * Checks to see if two given coordinates are valid. I.e - a coodinate is valid if it is greater than 0
     * and smaller than the dimensions of the parent grid
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    private boolean isValid(int i, int j) {
        return i > 0
                && j > 0
                && i <= N
                && j <= N;
    }

    /**
     * Throws an error if the given coordinates are valid (the valid state comes from the `isValid` function
     * @param i Node row
     * @param j Node column
     */
    private void doOutOfBoundsCheck(int i, int j) {
        if (!isValid(i, j)) {
            throw new IndexOutOfBoundsException("Boo! Values are out of bounds");
        }
    }

    /**
     * Sets a given node coordinates to be open (if it isn't open already). First is sets the appropriate index of the
     * `openNodes` array to be true and then attempts to union with all adjacent open nodes (if any).
     *
     * If the node is in the first row then it will union with the virtual top node. If the node is in the last row
     * then it will union with the virtual bottom row.
     *
     * This does connections both for the internal `grid` WeightedQuickUnionUF as well as the `full` WeightedQuickUnionUF,
     * but checkes to make sure that the nodes in `full` never connect to the virtual bottom node.
     *
     * @param i Node row
     * @param j Node column
     */
    public void open(int i, int j) {
        doOutOfBoundsCheck(i, j);

        if (isOpen(i, j)) {
            // No need to open this again as it's already open
            return;
        }

        int idx = getSingleArrayIdx(i, j);
        openNodes[idx] = true;


        // Node is in the top row. Union node in `grid` and `full` to the virtual top row.
        if (i == 1) {
            grid.union(top, idx);
            full.union(top, idx);
        }

        // Node is in the bottom row. Only union the node in `grid` to avoid backwash issue.
        if (i == N) {
            grid.union(bottom, idx);
        }

        // Union with the node above the given node if it is already open
        if (isValid(i - 1, j) && isOpen(i - 1, j)) {
            grid.union(getSingleArrayIdx(i - 1, j), idx);
            full.union(getSingleArrayIdx(i - 1, j), idx);
        }

        // Union with the node to the right of the given node if it is already open
        if (isValid(i, j + 1) && isOpen(i, j + 1)) {
            grid.union(getSingleArrayIdx(i, j + 1), idx);
            full.union(getSingleArrayIdx(i, j + 1), idx);
        }

        // Union with the node below the given node if it is already open
        if (isValid(i + 1, j) && isOpen(i + 1, j)) {
            grid.union(getSingleArrayIdx(i + 1, j), idx);
            full.union(getSingleArrayIdx(i + 1, j), idx);

        }

        // Union with the node to the left of the given node if it is already open
        if (isValid(i, j - 1) && isOpen(i, j - 1)) {
            grid.union(getSingleArrayIdx(i, j - 1), idx);
            full.union(getSingleArrayIdx(i, j - 1), idx);
        }
    }

    /**
     * Whether this node id open. This is checked against the internal `openNodes` array.
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    public boolean isOpen(int i, int j) {
        doOutOfBoundsCheck(i, j);

        return openNodes[getSingleArrayIdx(i, j)];
    }

    /**
     * Checks if a given node if 'full'. A node is considered full if it connects to the virtual top node.
     * Note that this check is against the full WeightedQuickUnionUF object which is not connected to the virtual
     * bottom node so that we don't get affected by backwash.
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    public boolean isFull(int i, int j) {
        int idx = getSingleArrayIdx(i, j);
        return full.connected(idx, top);
    }

    /**
     * Does this grid percolate? It percolates if the virtual top node connects to the virtual bottom node
     *
     * @return
     */
    public boolean percolates() {
        return grid.connected(top , bottom);
    }
}
//PercolationStats.java
import edu.princeton.cs.algs4.WeightedQuickUnionUF;

/**
 * Builds a N*N sized WeightedQuickUnionUF grid to mock create a simple percolation system. Initially all
 * nodes in the grid are blocked and must be opened. The grid is considered to percolate when there is a
 * connection from an open node on the top row to an open node on the bottom row.
 *
 * Whether a node is open or not is kept in an array. All connections are done through a WeightedQuickUnionUF object.
 *
 * We have a second WeightedQuickUnionUF object for checking fullness so as to not run into the backwash issue.
 */
public class Percolation {
    private WeightedQuickUnionUF grid;
    private WeightedQuickUnionUF full;
    private int N;
    private int top;
    private int bottom;
    private boolean[] openNodes;

    /**
     * Initialises an N * N WeightedQuickUnionUF object plus two extra nodes for the virtual top and virtual bottom
     * nodes. Creates an internal boolean array to keep track of whether a node is considered open or not.
     *
     * Also initialises a second N * N WeightedQuickUnionUF object plus one extra node as a second collection to check
     * for fullness and avoid the backwash issue.
     *
     * @param N The dimensions of the grid
     */
    public Percolation(int N) {
        if (N <= 0) {
            throw new java.lang.IllegalArgumentException("Woah, N must be greater than zero");
        }

        grid = new WeightedQuickUnionUF(N * N + 2);
        full = new WeightedQuickUnionUF(N * N + 1);

        this.N = N;

        top = getSingleArrayIdx(N, N) + 1;
        bottom = getSingleArrayIdx(N, N) + 2;

        openNodes = new boolean[N * N];
    }

    /**
     * Converts an index for a 0-based array from two grid coordinates which are 1-based. First checks to see if the
     * coordinates are out of bounds.
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    private int getSingleArrayIdx(int i, int j) {
        doOutOfBoundsCheck(i, j);

        return (N * (i - 1) + j) - 1;
    }

    /**
     * Checks to see if two given coordinates are valid. I.e - a coodinate is valid if it is greater than 0
     * and smaller than the dimensions of the parent grid
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    private boolean isValid(int i, int j) {
        return i > 0
                && j > 0
                && i <= N
                && j <= N;
    }

    /**
     * Throws an error if the given coordinates are valid (the valid state comes from the `isValid` function
     * @param i Node row
     * @param j Node column
     */
    private void doOutOfBoundsCheck(int i, int j) {
        if (!isValid(i, j)) {
            throw new IndexOutOfBoundsException("Boo! Values are out of bounds");
        }
    }

    /**
     * Sets a given node coordinates to be open (if it isn't open already). First is sets the appropriate index of the
     * `openNodes` array to be true and then attempts to union with all adjacent open nodes (if any).
     *
     * If the node is in the first row then it will union with the virtual top node. If the node is in the last row
     * then it will union with the virtual bottom row.
     *
     * This does connections both for the internal `grid` WeightedQuickUnionUF as well as the `full` WeightedQuickUnionUF,
     * but checkes to make sure that the nodes in `full` never connect to the virtual bottom node.
     *
     * @param i Node row
     * @param j Node column
     */
    public void open(int i, int j) {
        doOutOfBoundsCheck(i, j);

        if (isOpen(i, j)) {
            // No need to open this again as it's already open
            return;
        }

        int idx = getSingleArrayIdx(i, j);
        openNodes[idx] = true;


        // Node is in the top row. Union node in `grid` and `full` to the virtual top row.
        if (i == 1) {
            grid.union(top, idx);
            full.union(top, idx);
        }

        // Node is in the bottom row. Only union the node in `grid` to avoid backwash issue.
        if (i == N) {
            grid.union(bottom, idx);
        }

        // Union with the node above the given node if it is already open
        if (isValid(i - 1, j) && isOpen(i - 1, j)) {
            grid.union(getSingleArrayIdx(i - 1, j), idx);
            full.union(getSingleArrayIdx(i - 1, j), idx);
        }

        // Union with the node to the right of the given node if it is already open
        if (isValid(i, j + 1) && isOpen(i, j + 1)) {
            grid.union(getSingleArrayIdx(i, j + 1), idx);
            full.union(getSingleArrayIdx(i, j + 1), idx);
        }

        // Union with the node below the given node if it is already open
        if (isValid(i + 1, j) && isOpen(i + 1, j)) {
            grid.union(getSingleArrayIdx(i + 1, j), idx);
            full.union(getSingleArrayIdx(i + 1, j), idx);

        }

        // Union with the node to the left of the given node if it is already open
        if (isValid(i, j - 1) && isOpen(i, j - 1)) {
            grid.union(getSingleArrayIdx(i, j - 1), idx);
            full.union(getSingleArrayIdx(i, j - 1), idx);
        }
    }

    /**
     * Whether this node id open. This is checked against the internal `openNodes` array.
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    public boolean isOpen(int i, int j) {
        doOutOfBoundsCheck(i, j);

        return openNodes[getSingleArrayIdx(i, j)];
    }

    /**
     * Checks if a given node if 'full'. A node is considered full if it connects to the virtual top node.
     * Note that this check is against the full WeightedQuickUnionUF object which is not connected to the virtual
     * bottom node so that we don't get affected by backwash.
     *
     * @param i Node row
     * @param j Node column
     * @return
     */
    public boolean isFull(int i, int j) {
        int idx = getSingleArrayIdx(i, j);
        return full.connected(idx, top);
    }

    /**
     * Does this grid percolate? It percolates if the virtual top node connects to the virtual bottom node
     *
     * @return
     */
    public boolean percolates() {
        return grid.connected(top , bottom);
    }
}

猜你喜欢

转载自blog.csdn.net/u013453787/article/details/83383838