├── .gitignore ├── 8puzzle ├── Board.java ├── README.md └── Solver.java ├── README.md ├── collinear ├── BruteCollinearPoints.java ├── FastCollinearPoints.java ├── LineSegment.java ├── Point.java └── README.md ├── kdtree ├── KdTree.java ├── PointSET.java └── README.md ├── lib └── algs4.jar ├── percolation ├── Percolation.java ├── PercolationStats.java └── README.md └── queues ├── Deque.java ├── README.md ├── RandomizedQueue.java └── Subset.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | -------------------------------------------------------------------------------- /8puzzle/Board.java: -------------------------------------------------------------------------------- 1 | import java.util.LinkedList; 2 | import java.util.List; 3 | 4 | /** 5 | * @author Mincong Huang 6 | */ 7 | public class Board { 8 | 9 | private final int[][] blocks; 10 | private final int n; 11 | private int blankRow; 12 | private int blankCol; 13 | 14 | /** 15 | * Construct a board from an n-by-n array of blocks 16 | * (where blocks[i][j] = block in row i, column j) 17 | */ 18 | public Board(int[][] blocks) { 19 | 20 | if (blocks == null) { 21 | throw new NullPointerException(); 22 | } 23 | 24 | this.blocks = copyOf(blocks); 25 | n = blocks.length; 26 | blankRow = -1; 27 | blankCol = -1; 28 | 29 | for (int row = 0; row < n; row++) { 30 | for (int col = 0; col < n; col++) { 31 | if (blocks[row][col] == 0) { 32 | blankRow = row; 33 | blankCol = col; 34 | return; 35 | } 36 | } 37 | } 38 | } 39 | 40 | /** 41 | * Board dimension n 42 | */ 43 | public int dimension() { 44 | return n; 45 | } 46 | 47 | /** 48 | * Number of blocks out of place 49 | */ 50 | public int hamming() { 51 | int result = 0; 52 | for (int row = 0; row < n; row++) { 53 | for (int col = 0; col < n; col++) { 54 | if (row == blankRow && col == blankCol) { 55 | continue; 56 | } 57 | if (manhattan(row, col) != 0) { 58 | result++; 59 | } 60 | } 61 | } 62 | return result; 63 | } 64 | 65 | /** 66 | * Sum of Manhattan distances between blocks and goal 67 | */ 68 | public int manhattan() { 69 | int result = 0; 70 | for (int row = 0; row < n; row++) { 71 | for (int col = 0; col < n; col++) { 72 | if (row == blankRow && col == blankCol) { 73 | continue; 74 | } 75 | result += manhattan(row, col); 76 | } 77 | } 78 | return result; 79 | } 80 | 81 | private int manhattan(int row, int col) { 82 | int destVal = blocks[row][col] - 1; 83 | int destRow = destVal / n; 84 | int destCol = destVal % n; 85 | return Math.abs(destRow - row) + Math.abs(destCol - col); 86 | } 87 | 88 | /** 89 | * Is this board the goal board? 90 | */ 91 | public boolean isGoal() { 92 | return hamming() == 0; 93 | } 94 | 95 | /** 96 | * A board that is obtained by exchanging any pair of blocks. 97 | */ 98 | public Board twin() { 99 | int[][] cloned = copyOf(blocks); 100 | if (blankRow != 0) { 101 | swap(cloned, 0, 0, 0, 1); 102 | } else { 103 | swap(cloned, 1, 0, 1, 1); 104 | } 105 | return new Board(cloned); 106 | } 107 | 108 | private void swap(int[][] v, int rowA, int colA, int rowB, int colB) { 109 | int swap = v[rowA][colA]; 110 | v[rowA][colA] = v[rowB][colB]; 111 | v[rowB][colB] = swap; 112 | } 113 | 114 | /** 115 | * Does this board equal y? 116 | */ 117 | public boolean equals(Object y) { 118 | if (y == this) 119 | return true; 120 | if (y == null) 121 | return false; 122 | if (this.getClass() != y.getClass()) 123 | return false; 124 | Board that = (Board) y; 125 | if (this.blankCol != that.blankCol) 126 | return false; 127 | if (this.blankRow != that.blankRow) 128 | return false; 129 | if (this.n != that.n) 130 | return false; 131 | for (int row = 0; row < n; row++) 132 | for (int col = 0; col < n; col++) 133 | if (this.blocks[row][col] != that.blocks[row][col]) 134 | return false; 135 | return true; 136 | } 137 | 138 | private int[][] copyOf(int[][] matrix) { 139 | int[][] clone = new int[matrix.length][]; 140 | for (int row = 0; row < matrix.length; row++) { 141 | clone[row] = matrix[row].clone(); 142 | } 143 | return clone; 144 | } 145 | 146 | /** 147 | * All neighboring boards 148 | */ 149 | public Iterable neighbors() { 150 | 151 | List neighbors = new LinkedList<>(); 152 | 153 | if (blankRow > 0) { 154 | int[][] north = copyOf(blocks); 155 | swap(north, blankRow, blankCol, blankRow - 1, blankCol); 156 | neighbors.add(new Board(north)); 157 | } 158 | if (blankRow < n - 1) { 159 | int[][] south = copyOf(blocks); 160 | swap(south, blankRow, blankCol, blankRow + 1, blankCol); 161 | neighbors.add(new Board(south)); 162 | } 163 | if (blankCol > 0) { 164 | int[][] west = copyOf(blocks); 165 | swap(west, blankRow, blankCol, blankRow, blankCol - 1); 166 | neighbors.add(new Board(west)); 167 | } 168 | if (blankCol < n - 1) { 169 | int[][] east = copyOf(blocks); 170 | swap(east, blankRow, blankCol, blankRow, blankCol + 1); 171 | neighbors.add(new Board(east)); 172 | } 173 | return neighbors; 174 | } 175 | 176 | /** 177 | * String representation of this board (in the output format specified 178 | * below) 179 | */ 180 | public String toString() { 181 | StringBuilder builder = new StringBuilder(); 182 | builder.append(n).append("\n"); 183 | for (int row = 0; row < n; row++) { 184 | for (int col = 0; col < n; col++) { 185 | builder.append(String.format("%2d ", blocks[row][col])); 186 | } 187 | builder.append("\n"); 188 | } 189 | return builder.toString(); 190 | } 191 | 192 | /** 193 | * Unit tests (not graded) 194 | */ 195 | public static void main(String[] args) { 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /8puzzle/README.md: -------------------------------------------------------------------------------- 1 | # 8 Puzzle 2 | 3 | Write a program to solve the 8-puzzle problem (and its natural generalizations) 4 | using the _A* search algorithm_. 5 | 6 | The 8-puzzle problem is a puzzle invented and popularized by Noyes Palmer 7 | Chapman in the 1870s. It is played on a 3-by-3 grid with 8 square blocks labeled 8 | 1 through 8 and a blank square. Your goal is to rearrange the blocks so that 9 | they are in order, using as few moves as possible. You are permitted to slide 10 | blocks horizontally or vertically into the blank square. The following shows a 11 | sequence of legal moves from an initial board (left) to the goal board (right). 12 | 13 | 1 3 1 3 1 2 3 1 2 3 1 2 3 14 | 4 2 5 => 4 2 5 => 4 5 => 4 5 => 4 5 6 15 | 7 8 6 7 8 6 7 8 6 7 8 6 7 8 16 | 17 | initial 1 left 2 up 5 left goal 18 | 19 | For more informations, check the [official assignment description][1]. 20 | 21 | ## How to compile 22 | 23 | Mac OS / Linux / Windows 24 | 25 | javac -cp ../lib/* Board.java Solver.java 26 | 27 | [1]: http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 28 | -------------------------------------------------------------------------------- /8puzzle/Solver.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.In; 2 | import edu.princeton.cs.algs4.MinPQ; 3 | import edu.princeton.cs.algs4.StdOut; 4 | import java.util.Deque; 5 | import java.util.LinkedList; 6 | 7 | /** 8 | * @author Mincong Huang 9 | */ 10 | public class Solver { 11 | 12 | private boolean isSolvable; 13 | private MinPQ minPQ; 14 | private SearchNode solutionNode; 15 | 16 | /** 17 | * Find a solution to the initial board (using the A* algorithm) 18 | */ 19 | public Solver(Board initial) { 20 | 21 | solutionNode = null; 22 | minPQ = new MinPQ<>(); 23 | minPQ.insert(new SearchNode(initial, 0, null)); 24 | 25 | while (true) { 26 | 27 | SearchNode currNode = minPQ.delMin(); 28 | Board currBoard = currNode.getBoard(); 29 | 30 | if (currBoard.isGoal()) { 31 | isSolvable = true; 32 | solutionNode = currNode; 33 | break; 34 | } 35 | if (currBoard.hamming() == 2 && currBoard.twin().isGoal()) { 36 | isSolvable = false; 37 | break; 38 | } 39 | 40 | // Insert each neighbor except the board of the previous search node 41 | int moves = currNode.getMoves(); 42 | Board prevBoard = moves > 0 ? currNode.prev().getBoard() : null; 43 | 44 | for (Board nextBoard : currBoard.neighbors()) { 45 | if (prevBoard != null && nextBoard.equals(prevBoard)) { 46 | continue; 47 | } 48 | minPQ.insert(new SearchNode(nextBoard, moves + 1, currNode)); 49 | } 50 | } 51 | } 52 | 53 | private class SearchNode implements Comparable { 54 | 55 | private final SearchNode prev; 56 | private final Board board; 57 | private final int moves; 58 | 59 | SearchNode(Board board, int moves, SearchNode prev) { 60 | this.board = board; 61 | this.moves = moves; 62 | this.prev = prev; 63 | } 64 | 65 | @Override 66 | public int compareTo(SearchNode that) { 67 | return this.priority() - that.priority(); 68 | } 69 | 70 | public int priority() { 71 | return board.manhattan() + moves; 72 | } 73 | 74 | public Board getBoard() { 75 | return board; 76 | } 77 | 78 | public int getMoves() { 79 | return moves; 80 | } 81 | 82 | public SearchNode prev() { 83 | return prev; 84 | } 85 | } 86 | 87 | /** 88 | * Is the initial board solvable? 89 | */ 90 | public boolean isSolvable() { 91 | return isSolvable; 92 | } 93 | 94 | /** 95 | * Min number of moves to solve initial board; -1 if unsolvable 96 | */ 97 | public int moves() { 98 | return isSolvable() ? solutionNode.getMoves() : -1; 99 | } 100 | 101 | /** 102 | * Sequence of boards in a shortest solution; null if unsolvable 103 | */ 104 | public Iterable solution() { 105 | if (!isSolvable) { 106 | return null; 107 | } 108 | Deque solution = new LinkedList<>(); 109 | SearchNode node = solutionNode; 110 | while (node != null) { 111 | solution.addFirst(node.getBoard()); 112 | node = node.prev(); 113 | } 114 | return solution; 115 | } 116 | 117 | /** 118 | * Solver test client, given by Princeton University. 119 | */ 120 | public static void main(String[] args) { 121 | 122 | // create initial board from file 123 | In in = new In(args[0]); 124 | int n = in.readInt(); 125 | int[][] blocks = new int[n][n]; 126 | for (int i = 0; i < n; i++) 127 | for (int j = 0; j < n; j++) 128 | blocks[i][j] = in.readInt(); 129 | Board initial = new Board(blocks); 130 | 131 | // solve the puzzle 132 | Solver solver = new Solver(initial); 133 | 134 | // print solution to standard output 135 | if (!solver.isSolvable()) 136 | StdOut.println("No solution possible"); 137 | else { 138 | StdOut.println("Minimum number of moves = " + solver.moves()); 139 | for (Board board : solver.solution()) 140 | StdOut.println(board); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction to Algorithms 2 | 3 | Cousera online course, [Introduction to Algorithms][1], created by Princeton 4 | University, taught by: _Kevin Wayne_, Senior Lecturer and _Robert Sedgewick_, 5 | Professor. 6 | 7 | This course covers the essential information that every serious programmer needs 8 | to know about algorithms and data structures, with emphasis on applications and 9 | scientific performance analysis of Java implementations. Part I covers 10 | elementary data structures, sorting, and searching algorithms. Part II focuses 11 | on graph- and string-processing algorithms. 12 | 13 | This codebase only covers the Part I. However, all my assignments have score of 14 | 100 percent, so feel free to read them if you need any inspiration. 15 | 16 | Assignment | Name | Score 17 | :--- | :--- | --- 18 | Week 1 | [Percolation][w1] | 100/100 19 | Week 2 | [Queues][w2] | 100/100 20 | Week 3 | [Collinear][w3] | 100/100 21 | Week 4 | [8 Puzzle][w4] | 100/100 22 | Week 5 | [Kd-Trees][w5] | 100/100 23 | 24 | At the end, I wish you all a happy coding! :sunglasses::man_technologist: 25 | 26 | [1]: https://www.coursera.org/learn/introduction-to-algorithms 27 | [w1]: http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 28 | [w2]: http://coursera.cs.princeton.edu/algs4/assignments/queues.html 29 | [w3]: http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 30 | [w4]: http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 31 | [w5]: http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 32 | -------------------------------------------------------------------------------- /collinear/BruteCollinearPoints.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.In; 2 | import edu.princeton.cs.algs4.StdOut; 3 | import edu.princeton.cs.algs4.StdDraw; 4 | import java.util.Arrays; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * @author Mincong Huang 10 | */ 11 | public class BruteCollinearPoints { 12 | 13 | private final LineSegment[] lineSegments; 14 | 15 | /** 16 | * Finds all line segments containing 4 points. 17 | */ 18 | public BruteCollinearPoints(Point[] points) { 19 | 20 | checkNull(points); 21 | Point[] sortedPoints = points.clone(); 22 | Arrays.sort(sortedPoints); 23 | checkDuplicate(sortedPoints); 24 | 25 | final int N = points.length; 26 | List list = new LinkedList<>(); 27 | 28 | for (int a = 0; a < N - 3; a++) { 29 | Point ptA = sortedPoints[a]; 30 | 31 | for (int b = a + 1; b < N - 2; b++) { 32 | Point ptB = sortedPoints[b]; 33 | double slopeAB = ptA.slopeTo(ptB); 34 | 35 | for (int c = b + 1; c < N - 1; c++) { 36 | Point ptC = sortedPoints[c]; 37 | double slopeAC = ptA.slopeTo(ptC); 38 | if (slopeAB == slopeAC) { 39 | 40 | for (int d = c + 1; d < N; d++) { 41 | Point ptD = sortedPoints[d]; 42 | double slopeAD = ptA.slopeTo(ptD); 43 | if (slopeAB == slopeAD) { 44 | list.add(new LineSegment(ptA, ptD)); 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | lineSegments = list.toArray(new LineSegment[0]); 52 | } 53 | 54 | private void checkNull(Point[] points) { 55 | if (points == null) { 56 | throw new NullPointerException("The array \"Points\" is null."); 57 | } 58 | for (Point p : points) { 59 | if (p == null) { 60 | throw new NullPointerException( 61 | "The array \"Points\" contains null element."); 62 | } 63 | } 64 | } 65 | 66 | private void checkDuplicate(Point[] points) { 67 | for (int i = 0; i < points.length - 1; i++) { 68 | if (points[i].compareTo(points[i + 1]) == 0) { 69 | throw new IllegalArgumentException("Duplicate(s) found."); 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * The number of line segments. 76 | */ 77 | public int numberOfSegments() { 78 | return lineSegments.length; 79 | } 80 | 81 | /** 82 | * The line segments. 83 | */ 84 | public LineSegment[] segments() { 85 | return lineSegments.clone(); 86 | } 87 | 88 | /** 89 | * Simple client provided by Princeton University. 90 | */ 91 | public static void main(String[] args) { 92 | 93 | // read the n points from a file 94 | In in = new In(args[0]); 95 | int n = in.readInt(); 96 | Point[] points = new Point[n]; 97 | for (int i = 0; i < n; i++) { 98 | int x = in.readInt(); 99 | int y = in.readInt(); 100 | points[i] = new Point(x, y); 101 | } 102 | 103 | // draw the points 104 | StdDraw.enableDoubleBuffering(); 105 | StdDraw.setXscale(0, 32768); 106 | StdDraw.setYscale(0, 32768); 107 | for (Point p : points) { 108 | p.draw(); 109 | } 110 | StdDraw.show(); 111 | 112 | // print and draw the line segments 113 | BruteCollinearPoints collinear = new BruteCollinearPoints(points); 114 | for (LineSegment segment : collinear.segments()) { 115 | StdOut.println(segment); 116 | segment.draw(); 117 | } 118 | StdDraw.show(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /collinear/FastCollinearPoints.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.In; 2 | import edu.princeton.cs.algs4.StdOut; 3 | import edu.princeton.cs.algs4.StdDraw; 4 | import java.util.Arrays; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * A faster, sorting-based solution. Remarkably, it is possible to solve the 10 | * problem much faster than the brute-force solution. 11 | * 12 | * @author Mincong Huang 13 | */ 14 | public class FastCollinearPoints { 15 | 16 | private final LineSegment[] lineSegments; 17 | 18 | /** 19 | * Finds all line segments containing 4 points or more points. 20 | */ 21 | public FastCollinearPoints(Point[] points) { 22 | 23 | checkNull(points); 24 | Point[] sortedPoints = points.clone(); 25 | Arrays.sort(sortedPoints); 26 | checkDuplicate(sortedPoints); 27 | 28 | final int N = points.length; 29 | final List maxLineSegments = new LinkedList<>(); 30 | 31 | for (int i = 0; i < N; i++) { 32 | 33 | Point p = sortedPoints[i]; 34 | Point[] pointsBySlope = sortedPoints.clone(); 35 | Arrays.sort(pointsBySlope, p.slopeOrder()); 36 | 37 | // Notice the difference between "sortedPoints" & "pointsBySlope": 38 | // the below points are taken from "pointsBySlope". 39 | int x = 1; 40 | while (x < N) { 41 | 42 | LinkedList candidates = new LinkedList<>(); 43 | final double SLOPE_REF = p.slopeTo(pointsBySlope[x]); 44 | do { 45 | candidates.add(pointsBySlope[x++]); 46 | } while (x < N && p.slopeTo(pointsBySlope[x]) == SLOPE_REF); 47 | 48 | // Candidates have a max line segment if ... 49 | // 1. Candidates are collinear: At least 4 points are located 50 | // at the same line, so at least 3 without "p". 51 | // 2. The max line segment is created by the point "p" and the 52 | // last point in candidates: so "p" must be the smallest 53 | // point having this slope comparing to all candidates. 54 | if (candidates.size() >= 3 55 | && p.compareTo(candidates.peek()) < 0) { 56 | Point min = p; 57 | Point max = candidates.removeLast(); 58 | maxLineSegments.add(new LineSegment(min, max)); 59 | } 60 | } 61 | } 62 | lineSegments = maxLineSegments.toArray(new LineSegment[0]); 63 | } 64 | 65 | private void checkNull(Point[] points) { 66 | if (points == null) { 67 | throw new NullPointerException("The array \"Points\" is null."); 68 | } 69 | for (Point p : points) { 70 | if (p == null) { 71 | throw new NullPointerException( 72 | "The array \"Points\" contains null element."); 73 | } 74 | } 75 | } 76 | 77 | private void checkDuplicate(Point[] points) { 78 | for (int i = 0; i < points.length - 1; i++) { 79 | if (points[i].compareTo(points[i + 1]) == 0) { 80 | throw new IllegalArgumentException("Duplicate(s) found."); 81 | } 82 | } 83 | } 84 | 85 | /** 86 | * The number of line segments. 87 | */ 88 | public int numberOfSegments() { 89 | return lineSegments.length; 90 | } 91 | 92 | /** 93 | * The line segments. 94 | */ 95 | public LineSegment[] segments() { 96 | return lineSegments.clone(); 97 | } 98 | 99 | /** 100 | * Simple client provided by Princeton University. 101 | */ 102 | public static void main(String[] args) { 103 | 104 | // read the n points from a file 105 | In in = new In(args[0]); 106 | int n = in.readInt(); 107 | Point[] points = new Point[n]; 108 | for (int i = 0; i < n; i++) { 109 | int x = in.readInt(); 110 | int y = in.readInt(); 111 | points[i] = new Point(x, y); 112 | } 113 | 114 | // draw the points 115 | StdDraw.enableDoubleBuffering(); 116 | StdDraw.setXscale(0, 32768); 117 | StdDraw.setYscale(0, 32768); 118 | for (Point p : points) { 119 | p.draw(); 120 | } 121 | StdDraw.show(); 122 | 123 | // print and draw the line segments 124 | FastCollinearPoints collinear = new FastCollinearPoints(points); 125 | for (LineSegment segment : collinear.segments()) { 126 | StdOut.println(segment); 127 | segment.draw(); 128 | } 129 | StdDraw.show(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /collinear/LineSegment.java: -------------------------------------------------------------------------------- 1 | public class LineSegment { 2 | 3 | private final Point p; // one endpoint of this line segment 4 | private final Point q; // the other endpoint of this line segment 5 | 6 | /** 7 | * Initializes a new line segment. 8 | * 9 | * @param p one endpoint 10 | * @param q the other endpoint 11 | * @throws NullPointerException if either p or q 12 | * is null 13 | */ 14 | public LineSegment(Point p, Point q) { 15 | if (p == null || q == null) { 16 | throw new NullPointerException("argument is null"); 17 | } 18 | this.p = p; 19 | this.q = q; 20 | } 21 | 22 | 23 | /** 24 | * Draws this line segment to standard draw. 25 | */ 26 | public void draw() { 27 | p.drawTo(q); 28 | } 29 | 30 | /** 31 | * Returns a string representation of this line segment 32 | * This method is provide for debugging; 33 | * your program should not rely on the format of the string representation. 34 | * 35 | * @return a string representation of this line segment 36 | */ 37 | public String toString() { 38 | return p + " -> " + q; 39 | } 40 | 41 | /** 42 | * Throws an exception if called. The hashCode() method is not supported because 43 | * hashing has not yet been introduced in this course. Moreover, hashing does not 44 | * typically lead to good *worst-case* performance guarantees, as required on this 45 | * assignment. 46 | * 47 | * @throws UnsupportedOperationException if called 48 | */ 49 | public int hashCode() { 50 | throw new UnsupportedOperationException(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /collinear/Point.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdDraw; 2 | import java.util.Comparator; 3 | 4 | /** 5 | * An immutable data type for points in the plane. 6 | * 7 | * @author Mincong Huang 8 | */ 9 | public class Point implements Comparable { 10 | 11 | private final int x; // x-coordinate of this point 12 | private final int y; // y-coordinate of this point 13 | 14 | /** 15 | * Initializes a new point. 16 | * 17 | * @param x the x-coordinate of the point 18 | * @param y the y-coordinate of the point 19 | */ 20 | public Point(int x, int y) { 21 | /* DO NOT MODIFY */ 22 | this.x = x; 23 | this.y = y; 24 | } 25 | 26 | /** 27 | * Draws this point to standard draw. 28 | */ 29 | public void draw() { 30 | /* DO NOT MODIFY */ 31 | StdDraw.point(x, y); 32 | } 33 | 34 | /** 35 | * Draws the line segment between this point and the specified point 36 | * to standard draw. 37 | * 38 | * @param that the other point 39 | */ 40 | public void drawTo(Point that) { 41 | /* DO NOT MODIFY */ 42 | StdDraw.line(this.x, this.y, that.x, that.y); 43 | } 44 | 45 | /** 46 | * Returns the slope between this point and the specified point. 47 | * Formally, if the two points are (x0, y0) and (x1, y1), then the slope 48 | * is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be 49 | * +0.0 if the line segment connecting the two points is horizontal; 50 | * Double.POSITIVE_INFINITY if the line segment is vertical; 51 | * and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal. 52 | * 53 | * @param that the other point 54 | * @return the slope between this point and the specified point 55 | */ 56 | public double slopeTo(Point that) { 57 | /* YOUR CODE HERE */ 58 | if (this.x == that.x) { 59 | return this.y == that.y ? 60 | Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; 61 | } 62 | // avoid "-0.0". 63 | if (this.y == that.y) { 64 | return 0.0; 65 | } 66 | return (this.y - that.y) * 1.0 / (this.x - that.x); 67 | } 68 | 69 | /** 70 | * Compares two points by y-coordinate, breaking ties by x-coordinate. 71 | * Formally, the invoking point (x0, y0) is less than the argument point 72 | * (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1. 73 | * 74 | * @param that the other point 75 | * @return the value 0 if this point is equal to the argument 76 | * point (x0 = x1 and y0 = y1); 77 | * a negative integer if this point is less than the argument 78 | * point; and a positive integer if this point is greater than the 79 | * argument point 80 | */ 81 | public int compareTo(Point that) { 82 | /* YOUR CODE HERE */ 83 | return this.y == that.y ? this.x - that.x : this.y - that.y; 84 | } 85 | 86 | /** 87 | * Compares two points by the slope they make with this point. 88 | * The slope is defined as in the slopeTo() method. 89 | * 90 | * @return the Comparator that defines this ordering on points 91 | */ 92 | public Comparator slopeOrder() { 93 | /* YOUR CODE HERE */ 94 | return new SlopeComparator(this); 95 | } 96 | 97 | private class SlopeComparator implements Comparator { 98 | 99 | private final Point point; 100 | 101 | SlopeComparator(Point point) { 102 | this.point = point; 103 | } 104 | 105 | @Override 106 | public int compare(Point p1, Point p2) { 107 | double slope1 = p1.slopeTo(point); 108 | double slope2 = p2.slopeTo(point); 109 | return slope1 == slope2 ? 0 : (slope1 > slope2 ? 1 : -1); 110 | } 111 | } 112 | 113 | /** 114 | * Returns a string representation of this point. 115 | * This method is provide for debugging; 116 | * your program should not rely on the format of the string representation. 117 | * 118 | * @return a string representation of this point 119 | */ 120 | 121 | public String toString() { 122 | /* DO NOT MODIFY */ 123 | return "(" + x + ", " + y + ")"; 124 | } 125 | 126 | /** 127 | * Unit tests the Point data type. 128 | */ 129 | public static void main(String[] args) { 130 | /* YOUR CODE HERE */ 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /collinear/README.md: -------------------------------------------------------------------------------- 1 | # Pattern Recognition 2 | 3 | Given a set of _n_ distinct points in the plane, find every (maximal) line 4 | segment that connects a subset of 4 or more of the points. For more 5 | informations, check [the official assignment description][1]. 6 | 7 | ## How to compile 8 | 9 | Mac OS / Linux 10 | 11 | $ javac -cp ".:../lib/*" FastCollinearPoints.java BruteCollinearPoints.java Point.java 12 | 13 | Windows 14 | 15 | $ javac -cp ".;../lib/*" FastCollinearPoints.java BruteCollinearPoints.java Point.java 16 | 17 | [1]: http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 18 | -------------------------------------------------------------------------------- /kdtree/KdTree.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.Point2D; 2 | import edu.princeton.cs.algs4.RectHV; 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * 2d-tree implementation. A mutable data type that uses a 2d-tree to implement 8 | * the same API (but replace {@code PointSET} with {@code KdTree}). A 2d-tree is 9 | * a generalization of a BST to two-dimensional keys. The idea is to build a BST 10 | * with points in the nodes, using the x- and y-coordinates of the points as 11 | * keys in strictly alternating sequence. 12 | * 13 | * @author Mincong Huang 14 | */ 15 | public class KdTree { 16 | 17 | private enum Separator { VERTICAL, HORIZONTAL } 18 | private Node root; 19 | private int size; 20 | 21 | private static class Node { 22 | 23 | private final Separator sepr; 24 | private final RectHV rect; 25 | private final Point2D p; 26 | private Node leftBottom; 27 | private Node rightTop; 28 | 29 | Node(Point2D p, Separator sepr, RectHV rect) { 30 | this.p = p; 31 | this.sepr = sepr; 32 | this.rect = rect; 33 | } 34 | 35 | public Separator nextSepr() { 36 | return sepr == Separator.VERTICAL ? 37 | Separator.HORIZONTAL : Separator.VERTICAL; 38 | } 39 | 40 | public RectHV rectLB() { 41 | return sepr == Separator.VERTICAL 42 | ? new RectHV(rect.xmin(), rect.ymin(), p.x(), rect.ymax()) 43 | : new RectHV(rect.xmin(), rect.ymin(), rect.xmax(), p.y()); 44 | } 45 | 46 | public RectHV rectRT() { 47 | return sepr == Separator.VERTICAL 48 | ? new RectHV(p.x(), rect.ymin(), rect.xmax(), rect.ymax()) 49 | : new RectHV(rect.xmin(), p.y(), rect.xmax(), rect.ymax()); 50 | } 51 | 52 | public boolean isRightOrTopOf(Point2D q) { 53 | return (sepr == Separator.HORIZONTAL && p.y() > q.y()) 54 | || (sepr == Separator.VERTICAL && p.x() > q.x()); 55 | } 56 | } 57 | 58 | /** 59 | * Construct an empty set of points 60 | */ 61 | public KdTree() { 62 | root = null; 63 | size = 0; 64 | } 65 | 66 | /** 67 | * Is the set empty? 68 | */ 69 | public boolean isEmpty() { 70 | return size == 0; 71 | } 72 | 73 | /** 74 | * Number of points in the set 75 | */ 76 | public int size() { 77 | return size; 78 | } 79 | 80 | /** 81 | * Add the point to the set (if it is not already in the set) 82 | */ 83 | public void insert(Point2D p) { 84 | checkNull(p); 85 | if (root == null) { 86 | root = new Node(p, Separator.VERTICAL, new RectHV(0, 0, 1, 1)); 87 | size++; 88 | return; 89 | } 90 | 91 | // find node position for insertion 92 | Node prev = null; 93 | Node curr = root; 94 | do { 95 | if (curr.p.equals(p)) { 96 | return; 97 | } 98 | prev = curr; 99 | curr = curr.isRightOrTopOf(p) ? curr.leftBottom : curr.rightTop; 100 | } while (curr != null); 101 | 102 | // prepare new node and insert 103 | if (prev.isRightOrTopOf(p)) { 104 | prev.leftBottom = new Node(p, prev.nextSepr(), prev.rectLB()); 105 | } else { 106 | prev.rightTop = new Node(p, prev.nextSepr(), prev.rectRT()); 107 | } 108 | size++; 109 | } 110 | 111 | /** 112 | * Does the set contain point p? 113 | */ 114 | public boolean contains(Point2D p) { 115 | checkNull(p); 116 | Node node = root; 117 | while (node != null) { 118 | if (node.p.equals(p)) { 119 | return true; 120 | } 121 | node = node.isRightOrTopOf(p) ? node.leftBottom : node.rightTop; 122 | } 123 | return false; 124 | } 125 | 126 | /** 127 | * Draw all points to standard draw 128 | */ 129 | public void draw() { 130 | // TODO 131 | } 132 | 133 | /** 134 | * All points that are inside the rectangle 135 | */ 136 | public Iterable range(RectHV rect) { 137 | checkNull(rect); 138 | List results = new LinkedList<>(); 139 | addAll(root, rect, results); 140 | return results; 141 | } 142 | 143 | /** 144 | * Add all points under target node using DFS. 145 | */ 146 | private void addAll(Node node, RectHV rect, List results) { 147 | if (node == null) { 148 | return; 149 | } 150 | if (rect.contains(node.p)) { 151 | results.add(node.p); 152 | addAll(node.leftBottom, rect, results); 153 | addAll(node.rightTop, rect, results); 154 | return; 155 | } 156 | if (node.isRightOrTopOf(new Point2D(rect.xmin(), rect.ymin()))) { 157 | addAll(node.leftBottom, rect, results); 158 | } 159 | if (!node.isRightOrTopOf(new Point2D(rect.xmax(), rect.ymax()))) { 160 | addAll(node.rightTop, rect, results); 161 | } 162 | } 163 | 164 | /** 165 | * A nearest neighbor in the set to point p; null if the set is empty 166 | */ 167 | public Point2D nearest(Point2D p) { 168 | checkNull(p); 169 | return isEmpty() ? null : nearest(p, root.p, root); 170 | } 171 | 172 | private Point2D nearest(Point2D target, Point2D closest, Node node) { 173 | if (node == null) { 174 | return closest; 175 | } 176 | // Recursively search left/bottom or right/top 177 | // if it could contain a closer point 178 | double closestDist = closest.distanceTo(target); 179 | if (node.rect.distanceTo(target) < closestDist) { 180 | double nodeDist = node.p.distanceTo(target); 181 | if (nodeDist < closestDist) { 182 | closest = node.p; 183 | } 184 | if (node.isRightOrTopOf(target)) { 185 | closest = nearest(target, closest, node.leftBottom); 186 | closest = nearest(target, closest, node.rightTop); 187 | } else { 188 | closest = nearest(target, closest, node.rightTop); 189 | closest = nearest(target, closest, node.leftBottom); 190 | } 191 | } 192 | return closest; 193 | } 194 | 195 | private void checkNull(Object obj) { 196 | if (obj == null) { 197 | throw new NullPointerException(); 198 | } 199 | } 200 | 201 | /** 202 | * Unit testing of the methods (optional) 203 | */ 204 | public static void main(String[] args) { 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /kdtree/PointSET.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.Point2D; 2 | import edu.princeton.cs.algs4.RectHV; 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.TreeSet; 6 | 7 | /** 8 | * Brute-force implementation. A mutable data type that represents a set of 9 | * points in the unit square. Implemented by using a red-black BST of 10 | * {@code java.util.TreeSet}. 11 | * 12 | * @author Mincong Huang 13 | */ 14 | public class PointSET { 15 | 16 | private TreeSet points; 17 | 18 | /** 19 | * Construct an empty set of points 20 | */ 21 | public PointSET() { 22 | points = new TreeSet<>(); 23 | } 24 | 25 | /** 26 | * Is the set empty? 27 | */ 28 | public boolean isEmpty() { 29 | return points.isEmpty(); 30 | } 31 | 32 | /** 33 | * Number of points in the set 34 | */ 35 | public int size() { 36 | return points.size(); 37 | } 38 | 39 | /** 40 | * Add the point to the set (if it is not already in the set) 41 | */ 42 | public void insert(Point2D p) { 43 | checkNull(p); 44 | if (!points.contains(p)) { 45 | points.add(p); 46 | } 47 | } 48 | 49 | /** 50 | * Does the set contain point p? 51 | */ 52 | public boolean contains(Point2D p) { 53 | checkNull(p); 54 | return points.contains(p); 55 | } 56 | 57 | /** 58 | * Draw all points to standard draw 59 | */ 60 | public void draw() { 61 | // TODO 62 | } 63 | 64 | /** 65 | * All points that are inside the rectangle 66 | */ 67 | public Iterable range(RectHV rect) { 68 | checkNull(rect); 69 | Point2D minPoint = new Point2D(rect.xmin(), rect.ymin()); 70 | Point2D maxPoint = new Point2D(rect.xmax(), rect.ymax()); 71 | List pointsInRect = new LinkedList<>(); 72 | // The sub-set is inclusive for both extremities 73 | for (Point2D p : points.subSet(minPoint, true, maxPoint, true)) { 74 | // The y-coordinate has been validated by the minPoint & maxPoint 75 | if (p.x() >= rect.xmin() && p.x() <= rect.xmax()) { 76 | pointsInRect.add(p); 77 | } 78 | } 79 | return pointsInRect; 80 | } 81 | 82 | /** 83 | * A nearest neighbor in the set to point p; null if the set is empty 84 | */ 85 | public Point2D nearest(Point2D p) { 86 | 87 | checkNull(p); 88 | if (isEmpty()) { 89 | return null; 90 | } 91 | 92 | // 1. Find the 2 neighbour points in natural order, then find the 93 | // closest distance `d`. 94 | // 2. Widen the navigatable set to a circle of `d`, save the nearest. 95 | Point2D next = points.ceiling(p); 96 | Point2D prev = points.floor(p); 97 | if (next == null && prev == null) { 98 | return null; 99 | } 100 | 101 | double distNext = next == null ? Double.MAX_VALUE : p.distanceTo(next); 102 | double distPrev = prev == null ? Double.MAX_VALUE : p.distanceTo(prev); 103 | double d = Math.min(distNext, distPrev); 104 | 105 | Point2D minPoint = new Point2D(p.x(), p.y() - d); 106 | Point2D maxPoint = new Point2D(p.x(), p.y() + d); 107 | Point2D nearest = next == null ? prev : next; // cannot be both null 108 | 109 | // The sub-set is inclusive for both extremities 110 | for (Point2D candidate: points.subSet(minPoint, true, maxPoint, true)) { 111 | if (p.distanceTo(candidate) < p.distanceTo(nearest)) { 112 | nearest = candidate; 113 | } 114 | } 115 | return nearest; 116 | } 117 | 118 | private void checkNull(Object obj) { 119 | if (obj == null) { 120 | throw new NullPointerException(); 121 | } 122 | } 123 | 124 | /** 125 | * Unit testing of the methods (optional) 126 | */ 127 | public static void main(String[] args) { 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /kdtree/README.md: -------------------------------------------------------------------------------- 1 | # Kd-Trees 2 | 3 | Write a data type to represent a set of points in the unit square (all points 4 | have x- and y-coordinates between 0 and 1) using a 2d-tree to support efficient 5 | range search (find all of the points contained in a query rectangle) and nearest 6 | neighbor search (find a closest point to a query point). 2d-trees have numerous 7 | applications, ranging from classifying astronomical objects to computer 8 | animation to speeding up neural networks to mining data to image retrieval. For 9 | more information, check [the official assignment description][1]. 10 | 11 | ## How to compile 12 | 13 | Mac OS / Linux / Windows 14 | 15 | javac -cp ../lib/* PointSET.java KdTree.java 16 | 17 | [1]: http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 18 | -------------------------------------------------------------------------------- /lib/algs4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mincong-h/algorithm-princeton/a64989baee28e42dbae21e9fde4a8bdcab790109/lib/algs4.jar -------------------------------------------------------------------------------- /percolation/Percolation.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | import edu.princeton.cs.algs4.WeightedQuickUnionUF; 3 | 4 | /** 5 | * Percolation. Given a composite systems comprised of randomly distributed 6 | * insulating and metallic materials: what fraction of the materials need to be 7 | * metallic so that the composite system is an electrical conductor? Given a 8 | * porous landscape with water on the surface (or oil below), under what 9 | * conditions will the water be able to drain through to the bottom (or the oil 10 | * to gush through to the surface)? Scientists have defined an abstract process 11 | * known as percolation to model such situations. 12 | * 13 | * @author Mincong Huang 14 | * @author Nilesh Deokar (nieldeokar) 15 | */ 16 | public class Percolation { 17 | 18 | private final WeightedQuickUnionUF normalQU; 19 | private final WeightedQuickUnionUF backwashQU; 20 | private final boolean[] isOpen; 21 | private final int topIndex; 22 | private final int btmIndex; 23 | private final int n; 24 | private int openCount; 25 | 26 | /** 27 | * Create n-by-n grid, with all sites blocked 28 | * 29 | * @param n length and width of the grid 30 | */ 31 | public Percolation(int n) { 32 | if (n <= 0) { 33 | throw new IllegalArgumentException("n must be greater than 0."); 34 | } 35 | this.n = n; 36 | topIndex = 0; 37 | btmIndex = n * n + 1; 38 | backwashQU = new WeightedQuickUnionUF(n * n + 2); 39 | normalQU = new WeightedQuickUnionUF(n * n + 1); // wihout bottom index 40 | isOpen = new boolean[n * n + 2]; 41 | isOpen[topIndex] = true; 42 | isOpen[btmIndex] = true; 43 | } 44 | 45 | /** 46 | * Convert a 2D coordinate to 1D. 47 | * 48 | * @param row base-1 index of row 49 | * @param col base-1 index of column 50 | */ 51 | private int indexOf(int row, int col) { 52 | // check bounds 53 | if (row < 1 || row > n) { 54 | throw new IndexOutOfBoundsException("Row is out of bounds."); 55 | } 56 | if (col < 1 || col > n) { 57 | throw new IndexOutOfBoundsException("Column is out of bounds."); 58 | } 59 | return (row - 1) * n + col; 60 | } 61 | 62 | /** 63 | * Open site (row, col) if it is not open already 64 | * 65 | * @param row base-1 index of row 66 | * @param col base-1 index of column 67 | */ 68 | public void open(int row, int col) { 69 | int currIndex = indexOf(row, col); 70 | isOpen[currIndex] = true; 71 | openCount++; 72 | 73 | if (row == 1) { 74 | backwashQU.union(currIndex, topIndex); // Top 75 | normalQU.union(currIndex, topIndex); 76 | } 77 | if (row == n) { 78 | backwashQU.union(currIndex, btmIndex); // Bottom 79 | } 80 | tryUnion(row, col, row - 1, col); // North 81 | tryUnion(row, col, row + 1, col); // South 82 | tryUnion(row, col, row, col - 1); // West 83 | tryUnion(row, col, row, col + 1); // East 84 | } 85 | 86 | private void tryUnion(int rowA, int colA, int rowB, int colB) { 87 | // I assume that (rowA, colA) is correct. 88 | if (0 < rowB && rowB <= n && 0 < colB && colB <= n 89 | && isOpen(rowB, colB)) { 90 | backwashQU.union(indexOf(rowA, colA), indexOf(rowB, colB)); 91 | normalQU.union(indexOf(rowA, colA), indexOf(rowB, colB)); 92 | } 93 | } 94 | 95 | /** 96 | * Returns the number of open sites 97 | */ 98 | public int numberOfOpenSites(){ 99 | return openCount; 100 | } 101 | 102 | /** 103 | * Is site (row, col) open? 104 | * 105 | * @param row base-1 index of row 106 | * @param col base-1 index of column 107 | */ 108 | public boolean isOpen(int row, int col) { 109 | return isOpen[indexOf(row, col)]; 110 | } 111 | 112 | /** 113 | * Is site (row, col) full? 114 | * 115 | * @param row base-1 index of row 116 | * @param col base-1 index of column 117 | */ 118 | public boolean isFull(int row, int col) { 119 | return normalQU.connected(topIndex, indexOf(row, col)); 120 | } 121 | 122 | /** 123 | * Does the system percolate? 124 | */ 125 | public boolean percolates() { 126 | return backwashQU.connected(topIndex, btmIndex); 127 | } 128 | 129 | public static void main(String[] args) { 130 | StdOut.println("Please run PercolationStats instead."); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /percolation/PercolationStats.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | import edu.princeton.cs.algs4.StdRandom; 3 | import edu.princeton.cs.algs4.StdStats; 4 | 5 | /** 6 | * Perform a series of computational experiments. 7 | * 8 | * @author Mincong Huang 9 | * @author Nilesh Deokar (nieldeokar) 10 | */ 11 | public class PercolationStats { 12 | 13 | private final double[] fractions; 14 | private final double CONFIDENCE_95 = 1.96; 15 | 16 | /** 17 | * Perform trials independent experiments on an n-by-n grid. 18 | */ 19 | public PercolationStats(int n, int trials) { 20 | if (n <= 0) { 21 | throw new IllegalArgumentException("n <= 0."); 22 | } 23 | if (trials <= 0) { 24 | throw new IllegalArgumentException("trials <= 0."); 25 | } 26 | fractions = new double[trials]; 27 | for (int i = 0; i < trials; i++) { 28 | Percolation percolation = new Percolation(n); 29 | int openedSites = 0; 30 | while (!percolation.percolates()) { 31 | int row = StdRandom.uniform(n) + 1; // base-1 32 | int col = StdRandom.uniform(n) + 1; // base-1 33 | if (!percolation.isOpen(row, col)) { 34 | percolation.open(row, col); 35 | openedSites++; 36 | } 37 | } 38 | fractions[i] = openedSites * 1.0 / (n * n); 39 | } 40 | } 41 | 42 | /** 43 | * Sample mean of percolation threshold. 44 | */ 45 | public double mean() { 46 | return StdStats.mean(fractions); 47 | } 48 | 49 | /** 50 | * Sample standard deviation of percolation threshold. 51 | */ 52 | public double stddev() { 53 | return StdStats.stddev(fractions); 54 | } 55 | 56 | /** 57 | * Low end point of 95% confidence interval. 58 | */ 59 | public double confidenceLo() { 60 | return mean() - CONFIDENCE_95 * stddev() / Math.sqrt(fractions.length); 61 | } 62 | 63 | /** 64 | * High end point of 95% confidence interval. 65 | */ 66 | public double confidenceHi() { 67 | return mean() + CONFIDENCE_95 * stddev() / Math.sqrt(fractions.length); 68 | } 69 | 70 | /** 71 | * test client (described below) 72 | */ 73 | public static void main(String[] args) { 74 | 75 | int n = Integer.parseInt(args[0]); 76 | int trials = Integer.parseInt(args[1]); 77 | PercolationStats stats = new PercolationStats(n, trials); 78 | 79 | StdOut.println("mean = " + stats.mean()); 80 | StdOut.println("stddev = " + stats.stddev()); 81 | StdOut.println("95% confidence interval = " 82 | + stats.confidenceLo() + ", " 83 | + stats.confidenceHi()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /percolation/README.md: -------------------------------------------------------------------------------- 1 | # Percolation 2 | 3 | The program `PercolationStats` takes two command-line arguments _n_ and _T_, 4 | performs _T_ independent computational experiments on an _n_ * _n_ grid, and 5 | prints the mean, standard deviation, and the 95% confidence interval for the 6 | percolation threshold. For more informations, check [the official assignment 7 | description][1]. 8 | 9 | ## How to compile and run 10 | 11 | Mac OS / Linux 12 | 13 | $ javac -cp ../lib/* Percolation.java PercolationStats.java 14 | $ java -cp "../lib/*:." PercolationStats 200 1000 15 | 16 | Windows 17 | 18 | $ javac -cp ../lib/* Percolation.java PercolationStats.java 19 | $ java -cp "../lib/*;." PercolationStats 200 1000 20 | 21 | [1]: http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 22 | -------------------------------------------------------------------------------- /queues/Deque.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | import java.util.Iterator; 3 | import java.util.NoSuchElementException; 4 | 5 | /** 6 | * @author Mincong Huang 7 | */ 8 | public class Deque implements Iterable { 9 | 10 | private Node head; 11 | private Node tail; 12 | private int size; 13 | 14 | private class Node { 15 | 16 | Item item; 17 | Node prev; 18 | Node next; 19 | 20 | Node(Item item) { 21 | this.item = item; 22 | } 23 | } 24 | 25 | /** 26 | * Construct an empty deque 27 | */ 28 | public Deque() { 29 | head = new Node(null); // dummy head 30 | tail = new Node(null); // dummy tail 31 | head.next = tail; 32 | tail.prev = head; 33 | } 34 | 35 | /** 36 | * Is the deque empty? 37 | */ 38 | public boolean isEmpty() { 39 | return size == 0; 40 | } 41 | 42 | /** 43 | * Return the number of items on the deque 44 | */ 45 | public int size() { 46 | return size; 47 | } 48 | 49 | /** 50 | * Add the item to the front 51 | */ 52 | public void addFirst(Item item) { 53 | if (item == null) { 54 | throw new NullPointerException("Element e cannot be null."); 55 | } 56 | Node node = new Node(item); 57 | node.next = head.next; 58 | node.prev = head; 59 | head.next.prev = node; 60 | head.next = node; 61 | size++; 62 | } 63 | 64 | /** 65 | * Add the item to the end 66 | */ 67 | public void addLast(Item item) { 68 | if (item == null) { 69 | throw new NullPointerException("Element e connot be null."); 70 | } 71 | Node node = new Node(item); 72 | node.next = tail; 73 | node.prev = tail.prev; 74 | tail.prev.next = node; 75 | tail.prev = node; 76 | size++; 77 | } 78 | 79 | /** 80 | * Remove and return the item from the front 81 | */ 82 | public Item removeFirst() { 83 | if (size == 0) { 84 | throw new NoSuchElementException("Deque is empty."); 85 | } 86 | Node node = head.next; 87 | head.next = node.next; 88 | head.next.prev = head; 89 | size--; 90 | return node.item; 91 | } 92 | 93 | /** 94 | * Remove and return the item from the end 95 | */ 96 | public Item removeLast() { 97 | if (size == 0) { 98 | throw new NoSuchElementException("Deque is empty."); 99 | } 100 | Node node = tail.prev; 101 | tail.prev = node.prev; 102 | tail.prev.next = tail; 103 | size--; 104 | return node.item; 105 | } 106 | 107 | /** 108 | * Return an iterator over items in order from front to end 109 | */ 110 | @Override 111 | public Iterator iterator() { 112 | return new HeadFirstIterator(); 113 | } 114 | 115 | private class HeadFirstIterator implements Iterator { 116 | 117 | private Node curr = head; 118 | 119 | @Override 120 | public boolean hasNext() { 121 | return curr.next != tail; 122 | } 123 | 124 | @Override 125 | public Item next() { 126 | if (!hasNext()) { 127 | throw new NoSuchElementException("No more item."); 128 | } 129 | curr = curr.next; 130 | return curr.item; 131 | } 132 | 133 | @Override 134 | public void remove() { 135 | throw new UnsupportedOperationException("Remove unsupported."); 136 | } 137 | } 138 | 139 | /** 140 | * Serialization of the queue. 141 | * 142 | * TODO remove this method before your submission. 143 | */ 144 | @Override 145 | public String toString() { 146 | String result = ""; 147 | for (Item item : this) { 148 | result += "," + item; 149 | } 150 | if (!result.isEmpty()) { 151 | result = result.substring(1); 152 | } 153 | return "[" + result + "]"; 154 | } 155 | 156 | /** 157 | * Unit testing. 158 | * 159 | * TODO remove these tests before your submission, otherwise submission will 160 | * fail due to the usage of public method {@code toString()}. 161 | */ 162 | public static void main(String[] args) { 163 | 164 | StdOut.println("Tests start."); 165 | 166 | // Test 1: public operations 167 | Deque d1 = new Deque<>(); 168 | StdOut.println("Test 1A passed? " + d1.isEmpty()); 169 | StdOut.println("Test 1B passed? " + d1.toString().equals("[]")); 170 | d1.addLast(1); 171 | d1.addLast(2); 172 | StdOut.println("Test 1C passed? " + d1.toString().equals("[1,2]")); 173 | StdOut.println("Test 1D passed? " + (d1.size() == 2)); 174 | StdOut.println("Test 1E passed? " + (d1.iterator().next() == 1)); 175 | d1.addFirst(0); 176 | StdOut.println("Test 1F passed? " + d1.toString().equals("[0,1,2]")); 177 | d1.removeLast(); 178 | StdOut.println("Test 1G passed? " + d1.toString().equals("[0,1]")); 179 | d1.removeFirst(); 180 | StdOut.println("Test 1H passed? " + d1.toString().equals("[1]")); 181 | d1.removeFirst(); 182 | StdOut.println("Test 1I passed? " + d1.toString().equals("[]")); 183 | StdOut.println("Test 1J passed? " + d1.isEmpty()); 184 | StdOut.println("Test 1H passed? " + !d1.iterator().hasNext()); 185 | 186 | // Test 2: exceptions 187 | Deque d2 = new Deque<>(); 188 | try { 189 | d2.removeFirst(); 190 | StdOut.println("Test 2A passed? " + false); 191 | } catch (Exception e) { 192 | boolean result = e instanceof NoSuchElementException; 193 | StdOut.println("Test 2A passed? " + result); 194 | } 195 | try { 196 | d2.removeLast(); 197 | StdOut.println("Test 2B passed? " + false); 198 | } catch (Exception e) { 199 | boolean result = e instanceof NoSuchElementException; 200 | StdOut.println("Test 2B passed? " + result); 201 | } 202 | try { 203 | d2.addFirst(null); 204 | StdOut.println("Test 2C passed? " + false); 205 | } catch (Exception e) { 206 | boolean result = e instanceof NullPointerException; 207 | StdOut.println("Test 2C passed? " + result); 208 | } 209 | try { 210 | d2.addLast(null); 211 | StdOut.println("Test 2D passed? " + false); 212 | } catch (Exception e) { 213 | boolean result = e instanceof NullPointerException; 214 | StdOut.println("Test 2D passed? " + result); 215 | } 216 | try { 217 | d2.iterator().remove(); 218 | StdOut.println("Test 2F passed? " + false); 219 | } catch (Exception e) { 220 | boolean result = e instanceof UnsupportedOperationException; 221 | StdOut.println("Test 2F passed? " + result); 222 | } 223 | try { 224 | d2.iterator().next(); 225 | StdOut.println("Test 2G passed? " + false); 226 | } catch (Exception e) { 227 | boolean result = e instanceof NoSuchElementException; 228 | StdOut.println("Test 2G passed? " + result); 229 | } 230 | 231 | // Test 3: types 232 | Deque d3a = new Deque<>(); 233 | d3a.addFirst("Hello Algorithm"); 234 | StdOut.println("Test 3A passed? " + true); 235 | Deque d3b = new Deque<>(); 236 | d3b.addLast(3.1415926); 237 | StdOut.println("Test 3B passed? " + true); 238 | 239 | StdOut.println("Tests finished."); 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /queues/README.md: -------------------------------------------------------------------------------- 1 | # Deques and Randomized Queues 2 | 3 | The client program `Subset.java` takes a command-line integer _k_; reads in a 4 | sequence of _N_ strings from standard input using `StdIn.readString()`; and 5 | prints out exactly _k_ of them, uniformly at random. Each item from the sequence 6 | can be printed out at most once. You may assume that _0 ≤ k ≤ n_, where _n_ is 7 | the number of string on standard input. For more information, check [the 8 | official assignment description][1]. 9 | 10 | ## How to compile and run 11 | 12 | Mac OS / Linux 13 | 14 | $ javac -cp ../lib/* Deque.java RandomizedQueue.java Subset.java 15 | $ echo A B C D E F G H I | java -cp ".:../lib/*" Subset 3 16 | $ echo AA BB BB BB BB BB CC CC | java -cp ".:../lib/*" Subset 8 17 | 18 | Windows 19 | 20 | $ javac -cp ../lib/* Deque.java RandomizedQueue.java Subset.java 21 | $ echo A B C D E F G H I | java -cp ".;../lib/*" Subset 3 22 | $ echo AA BB BB BB BB BB CC CC | java -cp ".;../lib/*" Subset 8 23 | 24 | [1]: http://coursera.cs.princeton.edu/algs4/assignments/queues.html 25 | -------------------------------------------------------------------------------- /queues/RandomizedQueue.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdOut; 2 | import edu.princeton.cs.algs4.StdRandom; 3 | import java.util.Iterator; 4 | import java.util.NoSuchElementException; 5 | 6 | /** 7 | * @author Mincong Huang 8 | */ 9 | public class RandomizedQueue implements Iterable { 10 | 11 | private Item[] array; 12 | private int lastIndex; 13 | 14 | /** 15 | * Construct an empty randomized queue 16 | */ 17 | public RandomizedQueue() { 18 | // Type Item is only known at runtime. 19 | @SuppressWarnings("unchecked") 20 | Item[] a = (Item[]) new Object[1]; 21 | array = a; 22 | lastIndex = -1; 23 | } 24 | 25 | /** 26 | * Is the queue empty? 27 | */ 28 | public boolean isEmpty() { 29 | return size() == 0; 30 | } 31 | 32 | /** 33 | * Return the number of items on the queue 34 | */ 35 | public int size() { 36 | return lastIndex + 1; 37 | } 38 | 39 | /** 40 | * Add the item 41 | */ 42 | public void enqueue(Item item) { 43 | if (item == null) { 44 | throw new NullPointerException("Element e cannot be null."); 45 | } 46 | // array is full 47 | if (lastIndex + 1 == array.length) { 48 | resize(array.length * 2); 49 | } 50 | array[++lastIndex] = item; 51 | } 52 | 53 | /** 54 | * Remove and return a random item 55 | */ 56 | public Item dequeue() { 57 | if (isEmpty()) { 58 | throw new NoSuchElementException("RandomizedQueue is empty."); 59 | } 60 | int i = StdRandom.uniform(lastIndex + 1); 61 | Item removed = array[i]; 62 | array[i] = array[lastIndex]; 63 | array[lastIndex--] = null; 64 | // resize array if it is only 25% full 65 | if (size() > 0 && size() == array.length / 4) { 66 | resize(array.length / 2); 67 | } 68 | return removed; 69 | } 70 | 71 | /** 72 | * Return (but do not remove) a random item 73 | */ 74 | public Item sample() { 75 | if (isEmpty()) { 76 | throw new NoSuchElementException("RandomizedQueue is empty."); 77 | } 78 | Item sample = null; 79 | while (sample == null) { 80 | sample = array[StdRandom.uniform(lastIndex + 1)]; 81 | } 82 | return sample; 83 | } 84 | 85 | private void resize(int newCapacity) { 86 | @SuppressWarnings("unchecked") 87 | Item[] newArray = (Item[]) new Object[newCapacity]; 88 | int i = 0, j = 0; 89 | while (i <= lastIndex) { 90 | newArray[j++] = array[i++]; 91 | } 92 | array = newArray; 93 | lastIndex = j - 1; 94 | } 95 | 96 | /** 97 | * Return an independent iterator over items in random order 98 | */ 99 | public Iterator iterator() { 100 | return new RandomizedIterator(); 101 | } 102 | 103 | private class RandomizedIterator implements Iterator { 104 | 105 | private Item[] copiedArray; 106 | private int copiedLastIndex; 107 | 108 | RandomizedIterator() { 109 | @SuppressWarnings("unchecked") 110 | Item[] a = (Item[]) new Object[lastIndex + 1]; 111 | for (int i = 0; i <= lastIndex; i++) { 112 | a[i] = array[i]; 113 | } 114 | copiedArray = a; 115 | copiedLastIndex = lastIndex; 116 | } 117 | 118 | @Override 119 | public boolean hasNext() { 120 | return copiedLastIndex >= 0; 121 | } 122 | 123 | @Override 124 | public Item next() { 125 | if (!hasNext()) { 126 | throw new NoSuchElementException("No more item."); 127 | } 128 | int i = StdRandom.uniform(copiedLastIndex + 1); 129 | Item item = copiedArray[i]; 130 | copiedArray[i] = copiedArray[copiedLastIndex]; 131 | copiedArray[copiedLastIndex--] = null; 132 | return item; 133 | } 134 | 135 | @Override 136 | public void remove() { 137 | throw new UnsupportedOperationException("Remove unsupported."); 138 | } 139 | } 140 | 141 | /** 142 | * Serialization of the queue. 143 | * 144 | * TODO remove this method before your submission. 145 | */ 146 | @Override 147 | public String toString() { 148 | String result = ""; 149 | for (int i = 0; i <= lastIndex; i++) { 150 | result += "," + array[i]; 151 | } 152 | if (!result.isEmpty()) { 153 | result = result.substring(1); 154 | } 155 | return "[" + result + "]"; 156 | } 157 | 158 | /** 159 | * Unit testing. 160 | * 161 | * TODO remove these tests before your submission, otherwise submission will 162 | * fail due to the usage of public method {@code toString()}. 163 | */ 164 | public static void main(String[] args) { 165 | 166 | StdOut.println("Tests start."); 167 | 168 | // Test 1: public opeations 169 | RandomizedQueue q1 = new RandomizedQueue<>(); 170 | StdOut.println("Test 1A passed? " + q1.isEmpty()); 171 | StdOut.println("Test 1B passed? " + q1.toString().equals("[]")); 172 | q1.enqueue(1); 173 | q1.enqueue(2); 174 | StdOut.println("Test 1C passed? " + q1.toString().equals("[1,2]")); 175 | StdOut.println("Test 1D passed? " + (q1.size() == 2)); 176 | int test1E = q1.iterator().next(); 177 | StdOut.println("Test 1E passed? " + (test1E == 1 || test1E == 2)); 178 | q1.enqueue(3); 179 | q1.enqueue(4); 180 | StdOut.println("Test 1F passed? " + q1.toString().equals("[1,2,3,4]")); 181 | q1.dequeue(); 182 | String test1G = q1.toString(); 183 | StdOut.println("Test 1G passed? " 184 | + (test1G.equals("[4,2,3]") 185 | || test1G.equals("[1,4,3]") 186 | || test1G.equals("[1,2,4]") 187 | || test1G.equals("[1,2,3]"))); 188 | q1.dequeue(); 189 | q1.dequeue(); 190 | // Queue should be resized when 25% full: the size will be reduced by 191 | // 50%. However, the unused elements in the new array are not visible 192 | // because they're excluded by the {@code toString()} method. 193 | String test1H = q1.toString(); 194 | StdOut.println("Test 1H passed? " 195 | + (test1H.equals("[1]") 196 | || test1H.equals("[2]") 197 | || test1H.equals("[3]") 198 | || test1H.equals("[4]"))); 199 | q1.dequeue(); 200 | StdOut.println("Test 1I passed? " + q1.toString().equals("[]")); 201 | StdOut.println("Test 1J passed? " + q1.isEmpty()); 202 | StdOut.println("Test 1K passed? " + !q1.iterator().hasNext()); 203 | StdOut.println("Test 1L passed? " + (q1.iterator() != q1.iterator())); 204 | q1.enqueue(1); 205 | StdOut.println("Test 1M passed? " + q1.toString().equals("[1]")); 206 | q1.enqueue(2); 207 | StdOut.println("Test 1N passed? " + q1.toString().equals("[1,2]")); 208 | 209 | // Test 2: exceptions 210 | RandomizedQueue q2 = new RandomizedQueue<>(); 211 | try { 212 | q2.dequeue(); 213 | StdOut.println("Test 2A passed? " + false); 214 | } catch (Exception e) { 215 | boolean result = e instanceof NoSuchElementException; 216 | StdOut.println("Test 2A passed? " + result); 217 | } 218 | try { 219 | q2.sample(); 220 | StdOut.println("Test 2B passed? " + false); 221 | } catch (Exception e) { 222 | boolean result = e instanceof NoSuchElementException; 223 | StdOut.println("Test 2B passed? " + result); 224 | } 225 | try { 226 | q2.enqueue(null); 227 | StdOut.println("Test 2C passed? " + false); 228 | } catch (Exception e) { 229 | boolean result = e instanceof NullPointerException; 230 | StdOut.println("Test 2C passed? " + result); 231 | } 232 | try { 233 | q2.iterator().remove(); 234 | StdOut.println("Test 2D passed? " + false); 235 | } catch (Exception e) { 236 | boolean result = e instanceof UnsupportedOperationException; 237 | StdOut.println("Test 2D passed? " + result); 238 | } 239 | try { 240 | q2.iterator().next(); 241 | StdOut.println("Test 2E passed? " + false); 242 | } catch (Exception e) { 243 | boolean result = e instanceof NoSuchElementException; 244 | StdOut.println("Test 2E passed? " + result); 245 | } 246 | 247 | // Test 3: types 248 | RandomizedQueue q3A = new RandomizedQueue<>(); 249 | q3A.enqueue("Hello Algorithm"); 250 | StdOut.println("Test 3A passed? " + true); 251 | RandomizedQueue q3B = new RandomizedQueue<>(); 252 | q3B.enqueue(3.1415926); 253 | StdOut.println("Test 3B passed? " + true); 254 | 255 | StdOut.println("Tests finished."); 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /queues/Subset.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.StdIn; 2 | import edu.princeton.cs.algs4.StdOut; 3 | 4 | /** 5 | * A client program that 6 | *
    7 | *
  • takes a command-line integer {@code k}; 8 | *
  • reads in a sequence of {@code N} strings from standard input using 9 | * {@code StdIn.readString()}; 10 | *
  • prints out exactly {@code k} of them, uniformly at random. 11 | *

    12 | * Each item from the sequence can be printed out at most once. You may assume 13 | * that {@code 0 ≤ k ≤ n}, where {@code n} is the number of string on standard 14 | * input. 15 | * 16 | * @author Mincong Huang 17 | */ 18 | public class Subset { 19 | 20 | public static void main(String[] args) { 21 | final int k = Integer.parseInt(args[0]); 22 | RandomizedQueue queue = new RandomizedQueue<>(); 23 | String[] tokens = StdIn.readAllStrings(); 24 | for (String token : tokens) { 25 | queue.enqueue(token); 26 | } 27 | for (int i = 0; i < k; i++) { 28 | StdOut.println(queue.dequeue()); 29 | } 30 | } 31 | } 32 | --------------------------------------------------------------------------------