├── README.md ├── lectures ├── part I │ ├── AnalysisOfAlgorithms.pdf │ ├── BalancedSearchTrees-2.pdf │ ├── BinarySearchTrees.pdf │ ├── ElementarySorts.pdf │ ├── ElementarySymbolTables.pdf │ ├── GeometricSearch.pdf │ ├── HashTables.pdf │ ├── Intro.pdf │ ├── Mergesort.pdf │ ├── PriorityQueues.pdf │ ├── Quicksort.pdf │ ├── SearchingApplications.pdf │ ├── StacksAndQueues.pdf │ └── UnionFind.pdf └── part II │ ├── DataCompression.pdf │ ├── DirectedGraphs.pdf │ ├── Intractability.pdf │ ├── Intro.pdf │ ├── LinearProgramming.pdf │ ├── MST.pdf │ ├── MaxFlow.pdf │ ├── Reductions.pdf │ ├── RegularExpressions.pdf │ ├── ShortestPaths.pdf │ ├── StringSorts.pdf │ ├── SubstringSearch.pdf │ ├── Tries.pdf │ └── UndirectedGraphs.pdf └── projects ├── 8puzzle ├── Board.java └── Solver.java ├── baseball └── BaseballElimination.java ├── boggle └── BoggleSolver.java ├── burrows ├── BurrowsWheeler.java ├── CircularSuffixArray.java └── MoveToFront.java ├── collinear ├── BruteCollinearPoints.java ├── FastCollinearPoints.java ├── LineSegment.java └── Point.java ├── kdtree ├── KdTree.java └── PointSET.java ├── percolation ├── InteractivePercolationVisualizer.java ├── Percolation.java ├── PercolationStats.java └── PercolationVisualizer.java ├── queues ├── Deque.java ├── Permutation.java └── RandomizedQueue.java └── wordnet ├── Outcast.java ├── SAP.java └── WordNet.java /README.md: -------------------------------------------------------------------------------- 1 | # Princeton Algorithm 2 | 3 | This repository contains my solution for the coursera course Algorithm I & II 4 | 5 | ## Useful Link 6 | 7 | [Coursera course website : part1](https://www.coursera.org/learn/algorithms-part1/home/welcome) 8 | 9 | [Coursera course website : part2](https://www.coursera.org/learn/algorithms-part2/home/welcome) 10 | 11 | [Project 1: percolation](https://coursera.cs.princeton.edu/algs4/assignments/percolation/specification.php) 12 | 13 | [Project 2 : Queues](https://coursera.cs.princeton.edu/algs4/assignments/queues/specification.php) 14 | 15 | [Project 3 : colinear](https://coursera.cs.princeton.edu/algs4/assignments/collinear/specification.php) 16 | 17 | [Project 4 : 8puzzle](https://coursera.cs.princeton.edu/algs4/assignments/8puzzle/specification.php) 18 | 19 | [Project 5 : kd-trees](https://coursera.cs.princeton.edu/algs4/assignments/kdtree/specification.php) 20 | 21 | [Project 6 : WordNet](https://coursera.cs.princeton.edu/algs4/assignments/wordnet/specification.php) 22 | 23 | [Project 7 : Seam-Carving](https://coursera.cs.princeton.edu/algs4/assignments/seam/specification.php) 24 | 25 | [Project 8 : Baseball Elimenation](https://coursera.cs.princeton.edu/algs4/assignments/baseball/specification.php) 26 | 27 | [Project 9 : Boggle](https://coursera.cs.princeton.edu/algs4/assignments/boggle/specification.php) 28 | 29 | [Project 10 : Burrows-Wheeler](https://coursera.cs.princeton.edu/algs4/assignments/burrows/specification.php) 30 | 31 | ## Tips for projects 32 | 33 | - project 1 : percolation 34 | 35 | Pay attention to the definition of the full site. If you add two virtual sites for optimization, you should may encounter the bug below : 36 | 37 | ``` 38 | for a 3x3 grid, do the following instructions in turn: 39 | open(1, 3), open(2, 3), open(3, 3), open(3, 1) 40 | then the grid should look like this: (# for blocked, * for open) 41 | # # * 42 | # # * 43 | * # * 44 | Obviously the site (3, 1) should not be full, because there is 45 | not a path from it to one top open site. But if you add two 46 | virtual sites, then the site (3, 1) will be connected with the 47 | bottom virtual site which is connected with the top virtual 48 | site through the straight line path on the right. 49 | ``` 50 | 51 | To solve this, my solution is use two union-find, one with two virtual sites, and another with just one top virtual site. 52 | 53 | - Project 2 : Queues 54 | 55 | - Deque (linked-list based): to avoid handling the special case for adding into an empty deque, I add a guard node for every deque, this simplifies the code gracefully. 56 | - RandomizedDeque (resizing array based) : to achieve const amortized time for deque, you can first randomly pick one item then switch it with the last element in the array. Don't confuse between size (the number of elements in the deque) and capacity (the number of elements the deque **can** contains). 57 | 58 | - Project 3 : collinear points 59 | 60 | - to avoid duplicated segment, I choose the strategy below : After sorting the points in terms of one specific point x, the first element must be the x itself. To add a new segment into your solution, you only need to ensure that x is the smallest point. 61 | 62 | - Project 5 : kd trees 63 | 64 | - Nearest() : if the two subtrees both need to be checked, first check the subtree which the query point lies in, and remember that after you check one subtree, you may now prune the other subtree. 65 | 66 | ### Wanna Learn More ? 67 | 68 | Check out [this repository](https://github.com/PKUFlyingPig/Self-learning-Computer-Science) which contains all my self-learning materials : ) -------------------------------------------------------------------------------- /lectures/part I/AnalysisOfAlgorithms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/AnalysisOfAlgorithms.pdf -------------------------------------------------------------------------------- /lectures/part I/BalancedSearchTrees-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/BalancedSearchTrees-2.pdf -------------------------------------------------------------------------------- /lectures/part I/BinarySearchTrees.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/BinarySearchTrees.pdf -------------------------------------------------------------------------------- /lectures/part I/ElementarySorts.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/ElementarySorts.pdf -------------------------------------------------------------------------------- /lectures/part I/ElementarySymbolTables.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/ElementarySymbolTables.pdf -------------------------------------------------------------------------------- /lectures/part I/GeometricSearch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/GeometricSearch.pdf -------------------------------------------------------------------------------- /lectures/part I/HashTables.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/HashTables.pdf -------------------------------------------------------------------------------- /lectures/part I/Intro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/Intro.pdf -------------------------------------------------------------------------------- /lectures/part I/Mergesort.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/Mergesort.pdf -------------------------------------------------------------------------------- /lectures/part I/PriorityQueues.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/PriorityQueues.pdf -------------------------------------------------------------------------------- /lectures/part I/Quicksort.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/Quicksort.pdf -------------------------------------------------------------------------------- /lectures/part I/SearchingApplications.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/SearchingApplications.pdf -------------------------------------------------------------------------------- /lectures/part I/StacksAndQueues.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/StacksAndQueues.pdf -------------------------------------------------------------------------------- /lectures/part I/UnionFind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part I/UnionFind.pdf -------------------------------------------------------------------------------- /lectures/part II/DataCompression.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/DataCompression.pdf -------------------------------------------------------------------------------- /lectures/part II/DirectedGraphs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/DirectedGraphs.pdf -------------------------------------------------------------------------------- /lectures/part II/Intractability.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/Intractability.pdf -------------------------------------------------------------------------------- /lectures/part II/Intro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/Intro.pdf -------------------------------------------------------------------------------- /lectures/part II/LinearProgramming.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/LinearProgramming.pdf -------------------------------------------------------------------------------- /lectures/part II/MST.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/MST.pdf -------------------------------------------------------------------------------- /lectures/part II/MaxFlow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/MaxFlow.pdf -------------------------------------------------------------------------------- /lectures/part II/Reductions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/Reductions.pdf -------------------------------------------------------------------------------- /lectures/part II/RegularExpressions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/RegularExpressions.pdf -------------------------------------------------------------------------------- /lectures/part II/ShortestPaths.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/ShortestPaths.pdf -------------------------------------------------------------------------------- /lectures/part II/StringSorts.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/StringSorts.pdf -------------------------------------------------------------------------------- /lectures/part II/SubstringSearch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/SubstringSearch.pdf -------------------------------------------------------------------------------- /lectures/part II/Tries.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/Tries.pdf -------------------------------------------------------------------------------- /lectures/part II/UndirectedGraphs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PKUFlyingPig/Princeton-Algorithm/367114bbb81f72e664c8e82016c967f5ed59ca9f/lectures/part II/UndirectedGraphs.pdf -------------------------------------------------------------------------------- /projects/8puzzle/Board.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | package PACKAGE_NAME; 8 | 9 | public class Board { 10 | public static void main(String[] args) { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /projects/8puzzle/Solver.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | package PACKAGE_NAME; 8 | 9 | public class Solver { 10 | public static void main(String[] args) { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /projects/baseball/BaseballElimination.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.FlowEdge; 8 | import edu.princeton.cs.algs4.FlowNetwork; 9 | import edu.princeton.cs.algs4.FordFulkerson; 10 | import edu.princeton.cs.algs4.In; 11 | import edu.princeton.cs.algs4.StdOut; 12 | 13 | import java.util.ArrayList; 14 | import java.util.HashMap; 15 | import java.util.HashSet; 16 | import java.util.Map; 17 | import java.util.Set; 18 | 19 | public class BaseballElimination { 20 | private final Map name2id; 21 | private final Map id2name; 22 | private final int[] win; 23 | private final int[] loss; 24 | private final int[] remain; 25 | private final int[][] game; 26 | private final int teamNum; 27 | private final boolean[] solved; 28 | private final boolean[] isOut; 29 | private final ArrayList> certificates; 30 | 31 | // create a baseball division from given filename in format specified below 32 | public BaseballElimination(String filename) { 33 | In in = new In(filename); 34 | teamNum = in.readInt(); 35 | win = new int[teamNum]; 36 | loss = new int[teamNum]; 37 | remain = new int[teamNum]; 38 | game = new int[teamNum][teamNum]; 39 | solved = new boolean[teamNum]; 40 | isOut = new boolean[teamNum]; 41 | certificates = new ArrayList<>(); 42 | for (int i = 0; i < teamNum; i++) { 43 | certificates.add(null); 44 | } 45 | name2id = new HashMap<>(); 46 | id2name = new HashMap<>(); 47 | for (int i = 0; i < teamNum; i++) { 48 | String team = in.readString(); 49 | name2id.put(team, i); 50 | id2name.put(i, team); 51 | win[i] = in.readInt(); 52 | loss[i] = in.readInt(); 53 | remain[i] = in.readInt(); 54 | for (int j = 0; j < teamNum; j++) { 55 | game[i][j] = in.readInt(); 56 | } 57 | } 58 | } 59 | 60 | // number of teams 61 | public int numberOfTeams() { 62 | return teamNum; 63 | } 64 | 65 | // all teams 66 | public Iterable teams() { 67 | return name2id.keySet(); 68 | } 69 | 70 | // number of wins for given team 71 | public int wins(String team) { 72 | if (!name2id.containsKey(team)) { 73 | throw new IllegalArgumentException("invalid team"); 74 | } 75 | return win[name2id.get(team)]; 76 | } 77 | 78 | // number of losses for given team 79 | public int losses(String team) { 80 | if (!name2id.containsKey(team)) { 81 | throw new IllegalArgumentException("invalid team"); 82 | } 83 | return loss[name2id.get(team)]; 84 | } 85 | 86 | // number of remaining games for given team 87 | public int remaining(String team) { 88 | if (!name2id.containsKey(team)) { 89 | throw new IllegalArgumentException("invalid team"); 90 | } 91 | return remain[name2id.get(team)]; 92 | } 93 | 94 | // number of remaining games between team1 and team2 95 | public int against(String team1, String team2) { 96 | if (!name2id.containsKey(team1) || !name2id.containsKey(team2)) { 97 | throw new IllegalArgumentException("invalid team"); 98 | } 99 | return game[name2id.get(team1)][name2id.get(team2)]; 100 | } 101 | 102 | // create the Flow Network for team whose id is id 103 | private FlowNetwork createNetwork(int id) { 104 | int s = 0; 105 | int t = teamNum * (teamNum - 1) / 2 + 2; 106 | int m = (teamNum - 1) * (teamNum - 2) / 2 + 1; 107 | FlowNetwork G = new FlowNetwork(t + 1); 108 | int temp = 0; 109 | for (int i = 0; i < teamNum; i++) { 110 | if (i == id) continue; 111 | for (int j = i + 1; j < teamNum; j++) { 112 | if (j == id) continue; 113 | temp++; 114 | G.addEdge(new FlowEdge(s, temp, game[i][j])); 115 | G.addEdge(new FlowEdge(temp, m + i, Double.POSITIVE_INFINITY)); 116 | G.addEdge(new FlowEdge(temp, m + j, Double.POSITIVE_INFINITY)); 117 | } 118 | } 119 | for (int i = 0; i < teamNum; i++) { 120 | if (i == id) continue; 121 | G.addEdge(new FlowEdge(m + i, t, win[id] + remain[id] - win[i])); 122 | } 123 | return G; 124 | } 125 | 126 | // solve the baseball elimination problem for given team 127 | private void solve(String team) { 128 | int id = name2id.get(team); 129 | if (solved[id]) return; 130 | solved[id] = true; 131 | // trivial elimination 132 | for (int i = 0; i < teamNum; i++) { 133 | if (win[id] + remain[id] < win[i]) { 134 | isOut[id] = true; 135 | certificates.set(id, new HashSet<>()); 136 | certificates.get(id).add(id2name.get(i)); 137 | return; 138 | } 139 | } 140 | 141 | // Nontrivial elimination 142 | int s = 0; 143 | int t = teamNum * (teamNum - 1) / 2 + 2; 144 | int m = (teamNum - 1) * (teamNum - 2) / 2 + 1; 145 | FlowNetwork G = createNetwork(id); 146 | FordFulkerson FF = new FordFulkerson(G, s, t); 147 | for (int i = 1; i < m; i++) { 148 | if (FF.inCut(i)) { 149 | isOut[id] = true; 150 | certificates.set(id, new HashSet<>()); 151 | for (int j = 0; j < teamNum; j++) { 152 | if (FF.inCut(j + m)) { 153 | certificates.get(id).add(id2name.get(j)); 154 | } 155 | } 156 | return; 157 | } 158 | } 159 | isOut[id] = false; 160 | } 161 | 162 | // is given team eliminated? 163 | public boolean isEliminated(String team) { 164 | if (!name2id.containsKey(team)) { 165 | throw new IllegalArgumentException("invalid team"); 166 | } 167 | if (!solved[name2id.get(team)]) solve(team); 168 | return isOut[name2id.get(team)]; 169 | } 170 | 171 | // subset R of teams that eliminates given team; null if not eliminated 172 | public Iterable certificateOfElimination(String team) { 173 | if (!name2id.containsKey(team)) { 174 | throw new IllegalArgumentException("invalid team"); 175 | } 176 | if (!solved[name2id.get(team)]) solve(team); 177 | return certificates.get(name2id.get(team)); 178 | } 179 | 180 | public static void main(String[] args) { 181 | BaseballElimination division = new BaseballElimination(args[0]); 182 | for (String team : division.teams()) { 183 | if (division.isEliminated(team)) { 184 | StdOut.print(team + " is eliminated by the subset R = { "); 185 | for (String t : division.certificateOfElimination(team)) { 186 | StdOut.print(t + " "); 187 | } 188 | StdOut.println("}"); 189 | } 190 | else { 191 | StdOut.println(team + " is not eliminated"); 192 | } 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /projects/boggle/BoggleSolver.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.In; 8 | import edu.princeton.cs.algs4.StdOut; 9 | 10 | import java.util.HashSet; 11 | import java.util.Set; 12 | 13 | public class BoggleSolver { 14 | private Node root; 15 | private Set validWords; 16 | private boolean[][] marked; 17 | 18 | // Initializes the data structure using the given array of strings as the dictionary. 19 | // (You can assume each word in the dictionary contains only the uppercase letters A through Z.) 20 | public BoggleSolver(String[] dictionary) { 21 | for (String s : dictionary) { 22 | put(s); 23 | } 24 | } 25 | 26 | private static class Node { 27 | private boolean exist = false; 28 | private Node[] next = new Node[26]; 29 | } 30 | 31 | private void put(String s) { 32 | root = put(root, s, 0); 33 | } 34 | 35 | private Node put(Node node, String s, int d) { 36 | if (node == null) { 37 | node = new Node(); 38 | } 39 | if (d == s.length()) { 40 | node.exist = true; 41 | return node; 42 | } 43 | if (d > s.length()) return node; 44 | char c = s.charAt(d); 45 | node.next[c - 'A'] = put(node.next[c - 'A'], s, d+1); 46 | return node; 47 | } 48 | 49 | private boolean get(String s) { 50 | return get(root, s, 0); 51 | } 52 | 53 | private boolean get(Node node, String s, int d) { 54 | if (node == null) return false; 55 | if (d == s.length()) { 56 | return node.exist; 57 | } 58 | char c = s.charAt(d); 59 | return get(node.next[c - 'A'], s, d+1); 60 | } 61 | 62 | 63 | private boolean inBoard(BoggleBoard board, int row, int col) { 64 | return row >= 0 && row < board.rows() && col >= 0 && col < board.cols(); 65 | } 66 | 67 | private void dfs(BoggleBoard board, Node node, int row, int col, String word) { 68 | marked[row][col] = true; 69 | char c = board.getLetter(row, col); 70 | String curWord = word + c; 71 | if (c == 'Q') { 72 | curWord += 'U'; 73 | node = node.next['U' - 'A']; 74 | } 75 | if (node == null) { 76 | marked[row][col] = false; 77 | return; 78 | } 79 | if (curWord.length() >= 3 && node.exist) validWords.add(curWord); 80 | for (int drow = -1; drow <= 1; drow++) 81 | for (int dcol = -1; dcol <= 1; dcol++) 82 | { 83 | if (drow == 0 && dcol == 0) continue; 84 | int newRow = row + drow; 85 | int newCol = col + dcol; 86 | if (!inBoard(board, newRow, newCol))continue; 87 | char nextChar = board.getLetter(newRow, newCol); 88 | if (node.next[nextChar - 'A'] != null && !marked[newRow][newCol]) { 89 | dfs(board, node.next[nextChar - 'A'], newRow, newCol, curWord); 90 | } 91 | } 92 | marked[row][col] = false; 93 | } 94 | 95 | // Returns the set of all valid words in the given Boggle board, as an Iterable. 96 | public Iterable getAllValidWords(BoggleBoard board) { 97 | validWords = new HashSet<>(); 98 | int m = board.rows(); 99 | int n = board.cols(); 100 | if (root == null) return validWords; 101 | for (int i = 0; i < m; i++) 102 | for (int j = 0; j < n; j++) { 103 | if (root.next[board.getLetter(i, j) - 'A'] != null) { 104 | marked = new boolean[m][n]; 105 | dfs(board, root.next[board.getLetter(i, j) - 'A'], i, j, ""); 106 | } 107 | } 108 | return validWords; 109 | } 110 | 111 | // Returns the score of the given word if it is in the dictionary, zero otherwise. 112 | // (You can assume the word contains only the uppercase letters A through Z.) 113 | public int scoreOf(String word) { 114 | if (!get(word)) return 0; 115 | int len = word.length(); 116 | if (len < 3) return 0; 117 | if (len <= 4) return 1; 118 | else if (len == 5) return 2; 119 | else if (len == 6) return 3; 120 | else if (len == 7) return 5; 121 | else return 11; 122 | } 123 | 124 | public static void main(String[] args) { 125 | In in = new In(args[0]); 126 | String[] dictionary = in.readAllStrings(); 127 | BoggleSolver solver = new BoggleSolver(dictionary); 128 | BoggleBoard board = new BoggleBoard(args[1]); 129 | int score = 0; 130 | for (String word : solver.getAllValidWords(board)) { 131 | StdOut.println(word); 132 | score += solver.scoreOf(word); 133 | } 134 | StdOut.println("Score = " + score); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /projects/burrows/BurrowsWheeler.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: FlyingPig 3 | * Date: 2021.4.19 4 | * Description: BurrowsWheeler transform 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.BinaryStdIn; 8 | import edu.princeton.cs.algs4.BinaryStdOut; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Arrays; 12 | 13 | public class BurrowsWheeler { 14 | 15 | private static int mod(int x, int a) { 16 | return (x + a) % a; 17 | } 18 | 19 | // apply Burrows-Wheeler transform, 20 | // reading from standard input and writing to standard output 21 | public static void transform() { 22 | String s = BinaryStdIn.readString(); 23 | ArrayList t = new ArrayList<>(); 24 | CircularSuffixArray CSA = new CircularSuffixArray(s); 25 | for (int i = 0; i < CSA.length(); i++) { 26 | int index = CSA.index(i); 27 | t.add(s.charAt(mod(index - 1, CSA.length()))); 28 | if (index == 0) BinaryStdOut.write(i); 29 | } 30 | for (char x : t) { 31 | BinaryStdOut.write(x); 32 | } 33 | BinaryStdOut.close(); 34 | } 35 | 36 | // apply Burrows-Wheeler inverse transform, 37 | // reading from standard input and writing to standard output 38 | public static void inverseTransform() { 39 | int first = BinaryStdIn.readInt(); 40 | ArrayList t = new ArrayList<>(); 41 | while (!BinaryStdIn.isEmpty()) { 42 | t.add(BinaryStdIn.readChar()); 43 | } 44 | char[] firstColumn = new char[t.size()]; 45 | int[] next = new int[t.size()]; 46 | for (int i = 0; i < t.size(); i++) { 47 | firstColumn[i] = t.get(i); 48 | } 49 | Arrays.sort(firstColumn); 50 | for (int i = 0; i < t.size(); ) { 51 | int j = i + 1; 52 | while (j < t.size() && firstColumn[j] == firstColumn[j - 1]) j++; 53 | for (int k = 0; k < t.size(); k++) { 54 | if (t.get(k) == firstColumn[i]) { 55 | next[i++] = k; 56 | if (i == j) break; 57 | } 58 | } 59 | } 60 | int pointer = first; 61 | for (int i = 0; i < next.length; i++) { 62 | BinaryStdOut.write(firstColumn[pointer]); 63 | pointer = next[pointer]; 64 | } 65 | BinaryStdOut.close(); 66 | } 67 | 68 | // if args[0] is "-", apply Burrows-Wheeler transform 69 | // if args[0] is "+", apply Burrows-Wheeler inverse transform 70 | public static void main(String[] args) { 71 | if (args[0].equals("-")) transform(); 72 | else if (args[0].equals("+")) inverseTransform(); 73 | else throw new IllegalArgumentException("Illegal command line argument"); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /projects/burrows/CircularSuffixArray.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: FlyingPig 3 | * Date: 2021.4.19 4 | * Description: CircularSuffixArray data structure for Burrows-Wheeler compression algorithm 5 | **************************************************************************** */ 6 | 7 | import java.util.Arrays; 8 | 9 | public class CircularSuffixArray { 10 | 11 | private final int[] indexes; 12 | private final int N; 13 | // circular suffix array of s 14 | public CircularSuffixArray(String s) { 15 | if (s == null) { 16 | throw new IllegalArgumentException("null string"); 17 | } 18 | N = s.length(); 19 | CircularSuffix[] suffixes = new CircularSuffix[N]; 20 | String text = s + s; 21 | for (int i = 0; i < N; i++) { 22 | suffixes[i] = new CircularSuffix(text, i); 23 | } 24 | Arrays.sort(suffixes); 25 | indexes = new int[N]; 26 | for (int i = 0; i < N; i++) { 27 | indexes[i] = suffixes[i].index; 28 | } 29 | } 30 | 31 | private static class CircularSuffix implements Comparable { 32 | private final String text; 33 | private final int index; 34 | 35 | private CircularSuffix(String s, int idx) { 36 | text = s; 37 | index = idx; 38 | } 39 | 40 | private int length() { 41 | return text.length() / 2; 42 | } 43 | 44 | private char charAt(int i) { 45 | return text.charAt(index + i); 46 | } 47 | 48 | public int compareTo(CircularSuffix that) { 49 | if (this == that) return 0; // optimization 50 | int n = Math.min(this.length(), that.length()); 51 | for (int i = 0; i < n; i++) { 52 | if (this.charAt(i) < that.charAt(i)) return -1; 53 | if (this.charAt(i) > that.charAt(i)) return +1; 54 | } 55 | return this.length() - that.length(); 56 | } 57 | } 58 | 59 | // length of s 60 | public int length() { 61 | return N; 62 | } 63 | 64 | // returns index of ith sorted suffix 65 | public int index(int i) { 66 | if (i < 0 || i >= N) { 67 | throw new IllegalArgumentException("index out of range"); 68 | } 69 | return indexes[i]; 70 | } 71 | 72 | // unit testing (required) 73 | public static void main(String[] args) { 74 | CircularSuffixArray CSA = new CircularSuffixArray("ABRACADABRA!"); 75 | System.out.println("length of s : " + CSA.length()); 76 | for (int i = 0; i < CSA.length(); i++) { 77 | System.out.println(CSA.index(i)); 78 | } 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /projects/burrows/MoveToFront.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: FlyingPig 3 | * Date: 2021.4.19 4 | * Description: MoveToFront encoding for Burrows-Wheeler compression algorithm 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.BinaryStdIn; 8 | import edu.princeton.cs.algs4.BinaryStdOut; 9 | 10 | import java.util.LinkedList; 11 | 12 | public class MoveToFront { 13 | 14 | private static LinkedList alphabet; 15 | private static final int R = 256; 16 | 17 | private static void initialize() { 18 | alphabet = new LinkedList<>(); 19 | for (char i = 0; i < R; i++) { 20 | alphabet.add(i); 21 | } 22 | } 23 | 24 | // apply move-to-front encoding, reading from standard input and writing to standard output 25 | public static void encode() { 26 | initialize(); 27 | String s = BinaryStdIn.readString(); 28 | char[] input = s.toCharArray(); 29 | for (int i = 0; i < input.length; i++) { 30 | int index = alphabet.indexOf(input[i]); 31 | BinaryStdOut.write(index, 8); 32 | char x = alphabet.remove(index); 33 | alphabet.add(0, x); 34 | } 35 | BinaryStdOut.close(); 36 | } 37 | 38 | // apply move-to-front decoding, reading from standard input and writing to standard output 39 | public static void decode() { 40 | initialize(); 41 | String s = BinaryStdIn.readString(); 42 | char[] input = s.toCharArray(); 43 | for (int i = 0; i < input.length; i++) { 44 | BinaryStdOut.write(alphabet.get(input[i])); 45 | char x = alphabet.remove(input[i]); 46 | alphabet.add(0, x); 47 | } 48 | BinaryStdOut.close(); 49 | } 50 | 51 | // if args[0] is "-", apply move-to-front encoding 52 | // if args[0] is "+", apply move-to-front decoding 53 | public static void main(String[] args) { 54 | if (args[0].equals("-")) encode(); 55 | else if (args[0].equals("+")) decode(); 56 | else throw new IllegalArgumentException("Illegal command line argument"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /projects/collinear/BruteCollinearPoints.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.In; 8 | import edu.princeton.cs.algs4.StdDraw; 9 | import edu.princeton.cs.algs4.StdOut; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class BruteCollinearPoints { 16 | private List collinearLineSegments = new ArrayList<>(); 17 | // finds all line segments containing 4 points 18 | public BruteCollinearPoints(Point[] points) { 19 | // corner case checking 20 | if (points == null) { 21 | throw new IllegalArgumentException("argument to constructor is null"); 22 | } 23 | for (Point p : points) { 24 | if (p == null) { 25 | throw new IllegalArgumentException("one point is null"); 26 | } 27 | } 28 | int len = points.length; 29 | for (int i = 0; i < len; i++) { 30 | for (int j = i + 1; j < len; j++) { 31 | if (points[i].compareTo(points[j]) == 0) { 32 | throw new IllegalArgumentException("repeated point"); 33 | } 34 | } 35 | } 36 | if (len < 4) { 37 | return; 38 | } 39 | 40 | Point[] tmp = Arrays.copyOf(points, len); 41 | Arrays.sort(tmp); 42 | //brute check 43 | for (int i = 0; i < len; i++) { 44 | for (int j = i + 1; j < len; j++) { 45 | for (int k = j + 1; k < len; k++) { 46 | for (int h = k + 1; h < len; h++) { 47 | double s1 = tmp[i].slopeTo(tmp[j]); 48 | double s2 = tmp[i].slopeTo(tmp[k]); 49 | double s3 = tmp[i].slopeTo(tmp[h]); 50 | if (s1 == s2 && s1 == s3) { 51 | collinearLineSegments.add(new LineSegment(tmp[i], tmp[h])); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | 59 | // the number of line segments 60 | public int numberOfSegments() { 61 | return collinearLineSegments.size(); 62 | } 63 | 64 | // the line segments 65 | public LineSegment[] segments() { 66 | LineSegment[] retValue = new LineSegment[numberOfSegments()]; 67 | int i = 0; 68 | for (LineSegment x : collinearLineSegments) { 69 | retValue[i++] = x; 70 | } 71 | return retValue; 72 | } 73 | 74 | public static void main(String[] args) { 75 | // read the n points from a file 76 | In in = new In(args[0]); 77 | int n = in.readInt(); 78 | Point[] points = new Point[n]; 79 | for (int i = 0; i < n; i++) { 80 | int x = in.readInt(); 81 | int y = in.readInt(); 82 | points[i] = new Point(x, y); 83 | } 84 | 85 | // draw the points 86 | StdDraw.enableDoubleBuffering(); 87 | StdDraw.setXscale(0, 32768); 88 | StdDraw.setYscale(0, 32768); 89 | for (Point p : points) { 90 | p.draw(); 91 | } 92 | StdDraw.show(); 93 | 94 | // print and draw the line segments 95 | BruteCollinearPoints collinear = new BruteCollinearPoints(points); 96 | for (LineSegment segment : collinear.segments()) { 97 | StdOut.println(segment); 98 | segment.draw(); 99 | } 100 | StdDraw.show(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /projects/collinear/FastCollinearPoints.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.In; 8 | import edu.princeton.cs.algs4.StdDraw; 9 | import edu.princeton.cs.algs4.StdOut; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class FastCollinearPoints { 16 | private List colliLineSegments= new ArrayList<>(); 17 | // finds all line segments containing 4 or more points 18 | public FastCollinearPoints(Point[] points) { 19 | // corner case checking 20 | if (points == null) { 21 | throw new IllegalArgumentException("argument to constructor is null"); 22 | } 23 | for (Point p : points) { 24 | if (p == null) { 25 | throw new IllegalArgumentException("one point is null"); 26 | } 27 | } 28 | int len = points.length; 29 | for (int i = 0; i < len; i++) { 30 | for (int j = i + 1; j < len; j++) { 31 | if (points[i].compareTo(points[j]) == 0) { 32 | throw new IllegalArgumentException("repeated point"); 33 | } 34 | } 35 | } 36 | if (len < 4) { 37 | return; 38 | } 39 | 40 | points = Arrays.copyOf(points, len); 41 | Arrays.sort(points); 42 | 43 | Point[] tmp = Arrays.copyOf(points, len); 44 | for (Point p : points) { 45 | Arrays.sort(tmp, p.slopeOrder()); 46 | // for (Point x : tmp) { 47 | // System.out.print(x + " "); 48 | // } 49 | // System.out.println(); 50 | for (int i = 1; i < len;) { 51 | int j = i + 1; 52 | while (j < len && p.slopeTo(tmp[i]) == p.slopeTo(tmp[j])) { 53 | j++; 54 | } 55 | if (j - i >= 3 && tmp[0].compareTo(min(tmp, i, j - 1)) < 0) { 56 | colliLineSegments.add(new LineSegment(tmp[0], max(tmp, i, j - 1))); 57 | } 58 | if (j == len) { 59 | break; 60 | } 61 | i = j; 62 | } 63 | } 64 | } 65 | 66 | private Point min(Point[] a, int lo, int hi) { 67 | if (lo > hi || a == null) { 68 | throw new IllegalArgumentException(); 69 | } 70 | Point ret = a[lo]; 71 | for (int i = lo + 1; i <= hi; i++) { 72 | if (ret.compareTo(a[i]) > 0) { 73 | ret = a[i]; 74 | } 75 | } 76 | return ret; 77 | } 78 | 79 | private Point max(Point[] a, int lo, int hi) { 80 | if (lo > hi || a == null) { 81 | throw new IllegalArgumentException(); 82 | } 83 | Point ret = a[lo]; 84 | for (int i = lo + 1; i <= hi; i++) { 85 | if (ret.compareTo(a[i]) < 0) { 86 | ret = a[i]; 87 | } 88 | } 89 | return ret; 90 | } 91 | 92 | // the number of line segments 93 | public int numberOfSegments() { 94 | return colliLineSegments.size(); 95 | } 96 | // the line segments 97 | public LineSegment[] segments() { 98 | LineSegment[] ret = new LineSegment[colliLineSegments.size()]; 99 | int i = 0; 100 | for (LineSegment x : colliLineSegments) { 101 | ret[i++] = x; 102 | } 103 | return ret; 104 | } 105 | public static void main(String[] args) { 106 | // read the n points from a file 107 | In in = new In(args[0]); 108 | int n = in.readInt(); 109 | Point[] points = new Point[n]; 110 | for (int i = 0; i < n; i++) { 111 | int x = in.readInt(); 112 | int y = in.readInt(); 113 | points[i] = new Point(x, y); 114 | } 115 | 116 | // draw the points 117 | StdDraw.enableDoubleBuffering(); 118 | StdDraw.setXscale(0, 32768); 119 | StdDraw.setYscale(0, 32768); 120 | for (Point p : points) { 121 | p.draw(); 122 | } 123 | StdDraw.show(); 124 | 125 | // print and draw the line segments 126 | FastCollinearPoints collinear = new FastCollinearPoints(points); 127 | for (LineSegment segment : collinear.segments()) { 128 | StdOut.println(segment); 129 | segment.draw(); 130 | } 131 | StdDraw.show(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /projects/collinear/LineSegment.java: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * Compilation: javac LineSegment.java 3 | * Execution: none 4 | * Dependencies: Point.java 5 | * 6 | * An immutable data type for Line segments in the plane. 7 | * For use on Coursera, Algorithms Part I programming assignment. 8 | * 9 | * DO NOT MODIFY THIS CODE. 10 | * 11 | *************************************************************************/ 12 | 13 | public class LineSegment { 14 | private final Point p; // one endpoint of this line segment 15 | private final Point q; // the other endpoint of this line segment 16 | 17 | /** 18 | * Initializes a new line segment. 19 | * 20 | * @param p one endpoint 21 | * @param q the other endpoint 22 | * @throws NullPointerException if either p or q 23 | * is null 24 | */ 25 | public LineSegment(Point p, Point q) { 26 | if (p == null || q == null) { 27 | throw new NullPointerException("argument is null"); 28 | } 29 | this.p = p; 30 | this.q = q; 31 | } 32 | 33 | 34 | /** 35 | * Draws this line segment to standard draw. 36 | */ 37 | public void draw() { 38 | p.drawTo(q); 39 | } 40 | 41 | /** 42 | * Returns a string representation of this line segment 43 | * This method is provide for debugging; 44 | * your program should not rely on the format of the string representation. 45 | * 46 | * @return a string representation of this line segment 47 | */ 48 | public String toString() { 49 | return p + " -> " + q; 50 | } 51 | 52 | /** 53 | * Throws an exception if called. The hashCode() method is not supported because 54 | * hashing has not yet been introduced in this course. Moreover, hashing does not 55 | * typically lead to good *worst-case* performance guarantees, as required on this 56 | * assignment. 57 | * 58 | * @throws UnsupportedOperationException if called 59 | */ 60 | public int hashCode() { 61 | throw new UnsupportedOperationException(); 62 | } 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /projects/collinear/Point.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Compilation: javac Point.java 3 | * Execution: java Point 4 | * Dependencies: none 5 | * 6 | * An immutable data type for points in the plane. 7 | * For use on Coursera, Algorithms Part I programming assignment. 8 | * 9 | ******************************************************************************/ 10 | 11 | import edu.princeton.cs.algs4.StdDraw; 12 | 13 | import java.util.Comparator; 14 | 15 | public class Point implements Comparable { 16 | 17 | private final int x; // x-coordinate of this point 18 | private final int y; // y-coordinate of this point 19 | 20 | /** 21 | * Initializes a new point. 22 | * 23 | * @param x the x-coordinate of the point 24 | * @param y the y-coordinate of the point 25 | */ 26 | public Point(int x, int y) { 27 | /* DO NOT MODIFY */ 28 | this.x = x; 29 | this.y = y; 30 | } 31 | 32 | /** 33 | * Draws this point to standard draw. 34 | */ 35 | public void draw() { 36 | /* DO NOT MODIFY */ 37 | StdDraw.point(x, y); 38 | } 39 | 40 | /** 41 | * Draws the line segment between this point and the specified point 42 | * to standard draw. 43 | * 44 | * @param that the other point 45 | */ 46 | public void drawTo(Point that) { 47 | /* DO NOT MODIFY */ 48 | StdDraw.line(this.x, this.y, that.x, that.y); 49 | } 50 | 51 | /** 52 | * Returns the slope between this point and the specified point. 53 | * Formally, if the two points are (x0, y0) and (x1, y1), then the slope 54 | * is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be 55 | * +0.0 if the line segment connecting the two points is horizontal; 56 | * Double.POSITIVE_INFINITY if the line segment is vertical; 57 | * and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal. 58 | * 59 | * @param that the other point 60 | * @return the slope between this point and the specified point 61 | */ 62 | public double slopeTo(Point that) { 63 | /* YOUR CODE HERE */ 64 | if (this.x == that.x) { 65 | if (this.y == that.y) { 66 | return Double.NEGATIVE_INFINITY; 67 | } 68 | return Double.POSITIVE_INFINITY; 69 | } 70 | if (this.y == that.y) { 71 | return +0.0; 72 | } 73 | return (double) (that.y - this.y) / (that.x - this.x); 74 | } 75 | 76 | /** 77 | * Compares two points by y-coordinate, breaking ties by x-coordinate. 78 | * Formally, the invoking point (x0, y0) is less than the argument point 79 | * (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1. 80 | * 81 | * @param that the other point 82 | * @return the value 0 if this point is equal to the argument 83 | * point (x0 = x1 and y0 = y1); 84 | * a negative integer if this point is less than the argument 85 | * point; and a positive integer if this point is greater than the 86 | * argument point 87 | */ 88 | public int compareTo(Point that) { 89 | /* YOUR CODE HERE */ 90 | if (this.x == that.x && this.y == that.y) { 91 | return 0; 92 | } 93 | boolean isLess = this.y < that.y || (this.y == that.y && this.x < that.x); 94 | return isLess ? -1 : 1; 95 | } 96 | 97 | private class SlopeComparator implements Comparator { 98 | public int compare(Point o1, Point o2) { 99 | Double slope1 = slopeTo(o1); 100 | Double slope2 = slopeTo(o2); 101 | return slope1.compareTo(slope2); 102 | } 103 | } 104 | /** 105 | * Compares two points by the slope they make with this point. 106 | * The slope is defined as in the slopeTo() method. 107 | * 108 | * @return the Comparator that defines this ordering on points 109 | */ 110 | public Comparator slopeOrder() { 111 | /* YOUR CODE HERE */ 112 | return new SlopeComparator(); 113 | } 114 | 115 | 116 | /** 117 | * Returns a string representation of this point. 118 | * This method is provide for debugging; 119 | * your program should not rely on the format of the string representation. 120 | * 121 | * @return a string representation of this point 122 | */ 123 | public String toString() { 124 | /* DO NOT MODIFY */ 125 | return "(" + x + ", " + y + ")"; 126 | } 127 | 128 | /** 129 | * Unit tests the Point data type. 130 | */ 131 | public static void main(String[] args) { 132 | /* YOUR CODE HERE */ 133 | Point p1 = new Point(1, 1); 134 | Point p2 = new Point(2, 2); 135 | Point p3 = new Point(0, 4); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /projects/kdtree/KdTree.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.Point2D; 8 | import edu.princeton.cs.algs4.RectHV; 9 | import edu.princeton.cs.algs4.StdDraw; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class KdTree { 15 | private class Node { 16 | /** odd node splits the space vertically 17 | * even node splits the space horizontally 18 | */ 19 | private boolean isOdd; 20 | private Point2D point; 21 | private int size; 22 | private Node left, right; 23 | private RectHV rect; 24 | public Node(boolean isOdd, Point2D p, int size, RectHV rect) { 25 | this.isOdd = isOdd; 26 | this.point = p; 27 | this.size = size; 28 | this.rect = rect; 29 | } 30 | 31 | public boolean isVertical() { 32 | return isOdd; 33 | } 34 | 35 | public RectHV leftRect() { 36 | if (isVertical()) { 37 | return new RectHV(rect.xmin(), rect.ymin(), point.x(), rect.ymax()); 38 | } else { 39 | return new RectHV(rect.xmin(), rect.ymin(), rect.xmax(), point.y()); 40 | } 41 | } 42 | 43 | public RectHV rightRect() { 44 | if (isVertical()) { 45 | return new RectHV(point.x(), rect.ymin(), rect.xmax(), rect.ymax()); 46 | } else { 47 | return new RectHV(rect.xmin(), point.y(), rect.xmax(), rect.ymax()); 48 | } 49 | } 50 | } 51 | private Node root; 52 | private double dist; 53 | private Point2D nearestPoint; 54 | 55 | public KdTree() { 56 | } 57 | 58 | // is the set empty? 59 | public boolean isEmpty() { 60 | return size() == 0; 61 | } 62 | 63 | private int size(Node node) { 64 | if (node == null) { 65 | return 0; 66 | } else { 67 | return node.size; 68 | } 69 | } 70 | // number of points in the set 71 | public int size() { 72 | return size(root); 73 | } 74 | 75 | private Node insertHelper(Point2D p, Node node, Node parent, boolean isLeft) { 76 | if (node == null) { 77 | if (parent == null) { 78 | return new Node(true, p, 1, new RectHV(0, 0, 1, 1)); 79 | } else { 80 | if (isLeft) { 81 | return new Node(!parent.isOdd, p, 1, parent.leftRect()); 82 | } else { 83 | return new Node(!parent.isOdd, p, 1, parent.rightRect()); 84 | } 85 | } 86 | } else if (node.point.equals(p)) { 87 | return node; 88 | } else if (node.isVertical()) { 89 | if (p.x() < node.point.x()) { 90 | node.left = insertHelper(p, node.left, node, true); 91 | } else { 92 | node.right = insertHelper(p, node.right, node, false); 93 | } 94 | } else { 95 | if (p.y() < node.point.y()) { 96 | node.left = insertHelper(p, node.left, node, true); 97 | } else { 98 | node.right = insertHelper(p, node.right, node, false); 99 | } 100 | } 101 | node.size = size(node.left) + size(node.right) + 1; 102 | return node; 103 | } 104 | 105 | // add the point to the set (if it is not already in the set) 106 | public void insert(Point2D p) { 107 | if (p == null) { 108 | throw new IllegalArgumentException(); 109 | } 110 | root = insertHelper(p, root, null, true); 111 | } 112 | 113 | private boolean contains(Node node, Point2D p) { 114 | if (node == null) { 115 | return false; 116 | } 117 | if (p.equals(node.point)) { 118 | return true; 119 | } 120 | if (node.isVertical()) { 121 | if (p.x() < node.point.x()) { 122 | return contains(node.left, p); 123 | } else { 124 | return contains(node.right, p); 125 | } 126 | } else { 127 | if (p.y() < node.point.y()) { 128 | return contains(node.left, p); 129 | } else { 130 | return contains(node.right, p); 131 | } 132 | } 133 | } 134 | // does the set contain point p? 135 | public boolean contains(Point2D p) { 136 | if (p == null) { 137 | throw new IllegalArgumentException(); 138 | } 139 | return contains(root, p); 140 | } 141 | 142 | private void draw(Node node, Node parent) { 143 | if (node == null) { 144 | return; 145 | } 146 | if (parent == null) { 147 | StdDraw.setPenColor(StdDraw.RED); 148 | StdDraw.setPenRadius(); 149 | StdDraw.line(node.point.x(), 0, node.point.x(), 1); 150 | } else if (node.isVertical()) { 151 | StdDraw.setPenColor(StdDraw.RED); 152 | StdDraw.setPenRadius(); 153 | StdDraw.line(node.point.x(), node.rect.ymin(), node.point.x(), node.rect.ymax()); 154 | } else { 155 | StdDraw.setPenColor(StdDraw.BLUE); 156 | StdDraw.setPenRadius(); 157 | StdDraw.line(node.rect.xmin(), node.point.y(), node.rect.xmax(), node.point.y()); 158 | } 159 | 160 | StdDraw.setPenColor(StdDraw.BLACK); 161 | StdDraw.setPenRadius(0.01); 162 | StdDraw.point(node.point.x(), node.point.y()); 163 | draw(node.left, node); 164 | draw(node.right, node); 165 | } 166 | 167 | // draw all points to standard draw 168 | public void draw() { 169 | draw(root, null); 170 | } 171 | 172 | private void range(RectHV rect, List points, Node node) { 173 | if (node == null) { 174 | return; 175 | } 176 | if (rect.contains(node.point)) { 177 | points.add(node.point); 178 | } 179 | if (node.isVertical()) { 180 | if (node.point.x() > rect.xmax()) { 181 | range(rect, points, node.left); 182 | } else if (node.point.x() < rect.xmin()) { 183 | range(rect, points, node.right); 184 | } else { 185 | range(rect, points, node.left); 186 | range(rect, points, node.right); 187 | } 188 | } else { 189 | if (node.point.y() > rect.ymax()) { 190 | range(rect, points, node.left); 191 | } else if (node.point.y() < rect.ymin()) { 192 | range(rect, points, node.right); 193 | } else { 194 | range(rect, points, node.left); 195 | range(rect, points, node.right); 196 | } 197 | } 198 | } 199 | 200 | // all points that are inside the rectangle (or on the boundary) 201 | public Iterable range(RectHV rect) { 202 | if (rect == null) { 203 | throw new IllegalArgumentException(); 204 | } 205 | List points = new ArrayList<>(); 206 | range(rect, points, root); 207 | return points; 208 | } 209 | 210 | private void nearest(Point2D p, Node node) { 211 | if (node == null) { 212 | return; 213 | } 214 | if (p.distanceSquaredTo(node.point) < dist) { 215 | nearestPoint = node.point; 216 | dist = p.distanceSquaredTo(node.point); 217 | } 218 | boolean searchLeft = false, searchRight = false; 219 | if (node.left != null && node.left.rect.distanceSquaredTo(p) < dist) { 220 | searchLeft = true; 221 | } 222 | if (node.right != null && node.right.rect.distanceSquaredTo(p) < dist) { 223 | searchRight = true; 224 | } 225 | if (searchLeft && searchRight) { 226 | if (node.isVertical()) { 227 | if (p.x() < node.point.x()) { 228 | nearest(p, node.left); 229 | if (node.right.rect.distanceSquaredTo(p) < dist) { 230 | nearest(p, node.right); 231 | } 232 | } else { 233 | nearest(p, node.right); 234 | if (node.left.rect.distanceSquaredTo(p) < dist) { 235 | nearest(p, node.left); 236 | } 237 | } 238 | } else { 239 | if (p.y() < node.point.y()) { 240 | nearest(p, node.left); 241 | if (node.right.rect.distanceSquaredTo(p) < dist) { 242 | nearest(p, node.right); 243 | } 244 | } else { 245 | nearest(p, node.right); 246 | if (node.left.rect.distanceSquaredTo(p) < dist) { 247 | nearest(p, node.left); 248 | } 249 | } 250 | } 251 | } else { 252 | if (searchLeft) { 253 | nearest(p, node.left); 254 | } 255 | if (searchRight) { 256 | nearest(p, node.right); 257 | } 258 | } 259 | } 260 | 261 | // a nearest neighbor in the set to point p; null if the set is empty 262 | public Point2D nearest(Point2D p) { 263 | if (p == null) { 264 | throw new IllegalArgumentException(); 265 | } 266 | dist = Double.MAX_VALUE; 267 | nearestPoint = null; 268 | nearest(p, root); 269 | // System.out.println("the number of nodes visited in order to find the nearest is " + visited); 270 | return nearestPoint; 271 | } 272 | 273 | public static void main(String[] args) { 274 | KdTree kdtree = new KdTree(); 275 | kdtree.insert(new Point2D(0.7, 0.2)); 276 | System.out.println(kdtree.size()); 277 | System.out.println(kdtree.contains(new Point2D(0.7, 0.2))); 278 | 279 | kdtree.insert(new Point2D(0.5, 0.4)); 280 | System.out.println(kdtree.size()); 281 | System.out.println(kdtree.contains(new Point2D(0.5, 0.4))); 282 | 283 | kdtree.insert(new Point2D(0.2, 0.3)); 284 | kdtree.insert(new Point2D(0.4, 0.7)); 285 | kdtree.insert(new Point2D(0.9, 0.6)); 286 | kdtree.draw(); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /projects/kdtree/PointSET.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.Point2D; 8 | import edu.princeton.cs.algs4.RectHV; 9 | import edu.princeton.cs.algs4.SET; 10 | 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | public class PointSET { 15 | private SET points; 16 | // construct an empty set of points 17 | public PointSET() { 18 | points = new SET<>(); 19 | } 20 | 21 | // is the set empty? 22 | public boolean isEmpty() { 23 | return points.isEmpty(); 24 | } 25 | 26 | // number of points in the set 27 | public int size() { 28 | return points.size(); 29 | } 30 | 31 | // add the point to the set (if it is not already in the set) 32 | public void insert(Point2D p) { 33 | if (p == null) { 34 | throw new IllegalArgumentException(); 35 | } 36 | points.add(p); 37 | } 38 | 39 | // does the set contain point p? 40 | public boolean contains(Point2D p) { 41 | if (p == null) { 42 | throw new IllegalArgumentException(); 43 | } 44 | return points.contains(p); 45 | } 46 | 47 | // draw all points to standard draw 48 | public void draw() { 49 | for (Point2D point : points) { 50 | point.draw(); 51 | } 52 | } 53 | 54 | // all points that are inside the rectangle (or on the boundary) 55 | public Iterable range(RectHV rect) { 56 | if (rect == null) { 57 | throw new IllegalArgumentException("rect is null"); 58 | } 59 | List containedPoints = new ArrayList<>(); 60 | for (Point2D point : points) { 61 | if (rect.contains(point)) { 62 | containedPoints.add(point); 63 | } 64 | } 65 | return containedPoints; 66 | } 67 | 68 | // a nearest neighbor in the set to point p; null if the set is empty 69 | public Point2D nearest(Point2D p) { 70 | if (p == null) { 71 | throw new IllegalArgumentException("point is null"); 72 | } 73 | Point2D nearestPoint = null; 74 | double dist = Double.MAX_VALUE; 75 | for (Point2D point : points) { 76 | if (p.distanceTo(point) < dist) { 77 | nearestPoint = point; 78 | dist = p.distanceTo(point); 79 | } 80 | } 81 | return nearestPoint; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /projects/percolation/InteractivePercolationVisualizer.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Compilation: javac InteractivePercolationVisualizer.java 3 | * Execution: java InteractivePercolationVisualizer n 4 | * Dependencies: PercolationVisualizer.java Percolation.java 5 | * StdDraw.java StdOut.java 6 | * 7 | * This program takes the grid size n as a command-line argument. 8 | * Then, the user repeatedly clicks sites to open with the mouse. 9 | * After each site is opened, it draws full sites in light blue, 10 | * open sites (that aren't full) in white, and blocked sites in black. 11 | * 12 | ******************************************************************************/ 13 | 14 | import edu.princeton.cs.algs4.StdDraw; 15 | import edu.princeton.cs.algs4.StdOut; 16 | 17 | public class InteractivePercolationVisualizer { 18 | 19 | public static void main(String[] args) { 20 | // n-by-n percolation system (read from command-line, default = 10) 21 | int n = 10; 22 | if (args.length == 1) n = Integer.parseInt(args[0]); 23 | 24 | // repeatedly open site specified my mouse click and draw resulting system 25 | StdOut.println(n); 26 | 27 | StdDraw.enableDoubleBuffering(); 28 | Percolation perc = new Percolation(n); 29 | PercolationVisualizer.draw(perc, n); 30 | StdDraw.show(); 31 | 32 | while (true) { 33 | 34 | // detected mouse click 35 | if (StdDraw.isMousePressed()) { 36 | 37 | // screen coordinates 38 | double x = StdDraw.mouseX(); 39 | double y = StdDraw.mouseY(); 40 | 41 | // convert to row i, column j 42 | int i = (int) (n - Math.floor(y)); 43 | int j = (int) (1 + Math.floor(x)); 44 | 45 | // open site (i, j) provided it's in bounds 46 | if (i >= 1 && i <= n && j >= 1 && j <= n) { 47 | if (!perc.isOpen(i, j)) { 48 | StdOut.println(i + " " + j); 49 | } 50 | perc.open(i, j); 51 | } 52 | 53 | // draw n-by-n percolation system 54 | PercolationVisualizer.draw(perc, n); 55 | StdDraw.show(); 56 | } 57 | 58 | StdDraw.pause(20); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /projects/percolation/Percolation.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: Alan Turing 3 | * Coursera User ID: 123456 4 | * Last modified: 1/1/2019 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.WeightedQuickUnionUF; 8 | 9 | public class Percolation { 10 | // creates n-by-n grid, with all sites initially blocked 11 | private WeightedQuickUnionUF uf; 12 | private WeightedQuickUnionUF ufForFull; 13 | private boolean[][] ifOpen; 14 | private int gridwidth; 15 | private int opensites; 16 | private int[] dx = {-1, 0, 0, 1}; 17 | private int[] dy = {0, -1, 1, 0}; 18 | private boolean isPercolated; 19 | public Percolation(int n) { 20 | if (n <= 0) { 21 | throw new IllegalArgumentException("n-by-n grid's n must be positive"); 22 | } 23 | uf = new WeightedQuickUnionUF(n * n + 2); 24 | ufForFull = new WeightedQuickUnionUF(n * n + 1); 25 | gridwidth = n; 26 | opensites = 0; 27 | isPercolated = false; 28 | ifOpen = new boolean[n][n]; 29 | for (int i = 0; i < n; i++) { 30 | for (int j = 0; j < n; j++) { 31 | ifOpen[i][j] = false; 32 | } 33 | } 34 | } 35 | 36 | /** decide if given point is in the grid. */ 37 | private boolean ifInGrid(int row, int col) { 38 | if (row <= 0 || row > gridwidth || col <= 0 || col > gridwidth) { 39 | return false; 40 | } 41 | return true; 42 | } 43 | 44 | /** connect the given site with its neighbours if the neighbour has been open. */ 45 | private void connectNeighbours(int row, int col) { 46 | int newRow, newCol; 47 | int currIndex = calcIndex(row, col); 48 | for (int i = 0; i < 4; i++) { 49 | newRow = row + dx[i]; 50 | newCol = col + dy[i]; 51 | if (ifInGrid(newRow, newCol) && isOpen(newRow, newCol)) { 52 | uf.union(calcIndex(newRow, newCol), currIndex); 53 | ufForFull.union(calcIndex(newRow, newCol), currIndex); 54 | } 55 | } 56 | } 57 | 58 | /** opens the site (row, col) if it is not open already. */ 59 | public void open(int row, int col) { 60 | if (!ifInGrid(row, col)) { 61 | throw new IllegalArgumentException("the given site (row, col) must in the n-by-n grid"); 62 | } 63 | int currIndex = calcIndex(row, col); 64 | if (!ifOpen[row - 1][col - 1]) { 65 | ifOpen[row - 1][col - 1] = true; 66 | if (row == 1) { 67 | uf.union(0, currIndex); 68 | ufForFull.union(0, currIndex); 69 | } 70 | if (row == gridwidth) { 71 | uf.union(gridwidth * gridwidth + 1, currIndex); 72 | } 73 | connectNeighbours(row, col); 74 | opensites++; 75 | } 76 | } 77 | 78 | /** is the site (row, col) open? */ 79 | public boolean isOpen(int row, int col) { 80 | if (!ifInGrid(row, col)) { 81 | throw new IllegalArgumentException("the given site (row, col) must in the n-by-n grid"); 82 | } 83 | return ifOpen[row - 1][col - 1]; 84 | } 85 | 86 | /** calculate the index for the given site (row, col), where the index starts at 1. */ 87 | private int calcIndex(int row, int col) { 88 | return (row - 1) * gridwidth + col; 89 | } 90 | 91 | /** is the site (row, col) full? */ 92 | public boolean isFull(int row, int col) { 93 | if (!ifInGrid(row, col)) { 94 | throw new IllegalArgumentException("the given site (row, col) must in the n-by-n grid"); 95 | } 96 | return ufForFull.find(calcIndex(row, col)) == ufForFull.find(0); 97 | } 98 | 99 | /** returns the number of open sites. */ 100 | public int numberOfOpenSites() { 101 | return opensites; 102 | } 103 | 104 | /** does the system percolate? */ 105 | public boolean percolates() { 106 | return uf.find(0) == uf.find(gridwidth * gridwidth + 1); 107 | } 108 | 109 | public static void main(String[] args) { 110 | Percolation perc = new Percolation(3); 111 | perc.open(1, 3); 112 | perc.open(2, 3); 113 | perc.open(3, 3); 114 | perc.open(3, 1); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /projects/percolation/PercolationStats.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: Alan Turing 3 | * Coursera User ID: 123456 4 | * Last modified: 1/1/2019 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.StdRandom; 8 | import edu.princeton.cs.algs4.StdStats; 9 | 10 | public class PercolationStats { 11 | private double[] percoThreshold; 12 | private double area; 13 | private int gridWidth; 14 | private int T; 15 | 16 | /** perform independent trials on an n-by-n grid. */ 17 | public PercolationStats(int n, int trials) { 18 | if (n <= 0 || trials <= 0){ 19 | throw new IllegalArgumentException(); 20 | } 21 | gridWidth = n; 22 | area = n * n; 23 | T = trials; 24 | percoThreshold = new double[T]; 25 | for (int i = 0; i < T; i++) { 26 | Percolation perc = new Percolation(n); 27 | while (!perc.percolates()) { 28 | int row = StdRandom.uniform(n) + 1; 29 | int col = StdRandom.uniform(n) + 1; 30 | perc.open(row, col); 31 | } 32 | percoThreshold[i] = perc.numberOfOpenSites() / area; 33 | } 34 | } 35 | 36 | /** sample mean of percolation threshold. */ 37 | public double mean() { 38 | return StdStats.mean(percoThreshold); 39 | } 40 | 41 | /** sample standard deviation of percolation threshold. */ 42 | public double stddev() { 43 | return StdStats.stddev(percoThreshold); 44 | } 45 | 46 | /** low endpoint of 95% confidence interval. */ 47 | public double confidenceLo() { 48 | double pBar = mean(); 49 | double s = stddev(); 50 | return pBar - 1.96 * s / Math.sqrt(T); 51 | } 52 | 53 | /** high endpoint of 95% confidence interval. */ 54 | public double confidenceHi() { 55 | double pBar = mean(); 56 | double s = stddev(); 57 | return pBar + 1.96 * s / Math.sqrt(T); 58 | } 59 | 60 | /** test client (see below). */ 61 | public static void main(String[] args) { 62 | if (args.length != 2) { 63 | System.out.println("Usage: java-algs4 PercolationStats n T"); 64 | return; 65 | } 66 | int n = Integer.parseInt(args[0]); 67 | int T = Integer.parseInt(args[1]); 68 | PercolationStats percStats = new PercolationStats(n, T); 69 | System.out.println("mean = " + percStats.mean()); 70 | System.out.println("stddev = " + percStats.stddev()); 71 | System.out.println("95% confidence interval = [" + percStats.confidenceLo() 72 | + ", " + percStats.confidenceHi() + "]"); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /projects/percolation/PercolationVisualizer.java: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * Compilation: javac PercolationVisualizer.java 3 | * Execution: java PercolationVisualizer input.txt 4 | * Dependencies: Percolation.java 5 | * 6 | * This program takes the name of a file as a command-line argument. 7 | * From that file, it 8 | * 9 | * - Reads the grid size n of the percolation system. 10 | * - Creates an n-by-n grid of sites (intially all blocked) 11 | * - Reads in a sequence of sites (row i, column j) to open. 12 | * 13 | * After each site is opened, it draws full sites in light blue, 14 | * open sites (that aren't full) in white, and blocked sites in black, 15 | * with with site (1, 1) in the upper left-hand corner. 16 | * 17 | ******************************************************************************/ 18 | 19 | import edu.princeton.cs.algs4.In; 20 | import edu.princeton.cs.algs4.StdDraw; 21 | 22 | import java.awt.Font; 23 | 24 | public class PercolationVisualizer { 25 | 26 | // delay in miliseconds (controls animation speed) 27 | private static final int DELAY = 100; 28 | 29 | // draw n-by-n percolation system 30 | public static void draw(Percolation perc, int n) { 31 | StdDraw.clear(); 32 | StdDraw.setPenColor(StdDraw.BLACK); 33 | StdDraw.setXscale(-0.05 * n, 1.05 * n); 34 | StdDraw.setYscale(-0.05 * n, 1.05 * n); // leave a border to write text 35 | StdDraw.filledSquare(n / 2.0, n / 2.0, n / 2.0); 36 | 37 | // draw n-by-n grid 38 | int opened = 0; 39 | for (int row = 1; row <= n; row++) { 40 | for (int col = 1; col <= n; col++) { 41 | if (perc.isFull(row, col)) { 42 | StdDraw.setPenColor(StdDraw.BOOK_LIGHT_BLUE); 43 | opened++; 44 | } 45 | else if (perc.isOpen(row, col)) { 46 | StdDraw.setPenColor(StdDraw.WHITE); 47 | opened++; 48 | } 49 | else 50 | StdDraw.setPenColor(StdDraw.BLACK); 51 | StdDraw.filledSquare(col - 0.5, n - row + 0.5, 0.45); 52 | } 53 | } 54 | 55 | // write status text 56 | StdDraw.setFont(new Font("SansSerif", Font.PLAIN, 12)); 57 | StdDraw.setPenColor(StdDraw.BLACK); 58 | StdDraw.text(0.25 * n, -0.025 * n, opened + " open sites"); 59 | if (perc.percolates()) StdDraw.text(0.75 * n, -0.025 * n, "percolates"); 60 | else StdDraw.text(0.75 * n, -0.025 * n, "does not percolate"); 61 | 62 | } 63 | 64 | public static void main(String[] args) { 65 | In in = new In(args[0]); // input file 66 | int n = in.readInt(); // n-by-n percolation system 67 | 68 | // turn on animation mode 69 | StdDraw.enableDoubleBuffering(); 70 | 71 | // repeatedly read in sites to open and draw resulting system 72 | Percolation perc = new Percolation(n); 73 | draw(perc, n); 74 | StdDraw.show(); 75 | StdDraw.pause(DELAY); 76 | while (!in.isEmpty()) { 77 | int i = in.readInt(); 78 | int j = in.readInt(); 79 | perc.open(i, j); 80 | draw(perc, n); 81 | StdDraw.show(); 82 | StdDraw.pause(DELAY); 83 | } 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /projects/queues/Deque.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: FlyingPig 3 | * Date: 2020.9.21 4 | * Description: deque implemented based on linked-list 5 | **************************************************************************** */ 6 | 7 | import java.util.Iterator; 8 | import java.util.NoSuchElementException; 9 | 10 | public class Deque implements Iterable { 11 | 12 | private class Node { 13 | Item value; 14 | Node next; 15 | Node pre; 16 | public Node() { 17 | value = null; 18 | next = null; 19 | pre = null; 20 | } 21 | public Node(Item value, Node pre, Node next) { 22 | this.value = value; 23 | this.pre = pre; 24 | this.next = next; 25 | } 26 | } 27 | 28 | private Node guard; 29 | private int size; 30 | // construct an empty deque 31 | public Deque() { 32 | guard = new Node(); 33 | guard.pre = guard; 34 | guard.next = guard; 35 | size = 0; 36 | } 37 | 38 | // is the deque empty? 39 | public boolean isEmpty() { 40 | return size == 0; 41 | } 42 | 43 | // return the number of items on the deque 44 | public int size() { 45 | return size; 46 | } 47 | 48 | // add the item to the front 49 | public void addFirst(Item item) { 50 | if (item == null) { 51 | throw new IllegalArgumentException("can not add null into the deque"); 52 | } 53 | Node first = new Node(item, guard, guard.next); 54 | guard.next.pre = first; 55 | guard.next = first; 56 | size++; 57 | } 58 | 59 | // add the item to the back 60 | public void addLast(Item item) { 61 | if (item == null) { 62 | throw new IllegalArgumentException("can not add null into the deque"); 63 | } 64 | Node last = new Node(item, guard.pre, guard); 65 | guard.pre.next = last; 66 | guard.pre = last; 67 | size++; 68 | } 69 | 70 | // remove and return the item from the front 71 | public Item removeFirst() { 72 | if (size == 0) { 73 | throw new NoSuchElementException("can not remove value from an empty deque"); 74 | } 75 | Item retValue = guard.next.value; 76 | guard.next.next.pre = guard; 77 | guard.next = guard.next.next; 78 | size--; 79 | return retValue; 80 | } 81 | 82 | // remove and return the item from the back 83 | public Item removeLast() { 84 | if (size == 0) { 85 | throw new NoSuchElementException("can not remove value from an empty deque"); 86 | } 87 | Item retValue = guard.pre.value; 88 | guard.pre.pre.next = guard; 89 | guard.pre = guard.pre.pre; 90 | size--; 91 | return retValue; 92 | } 93 | 94 | private class dequeIterator implements Iterator { 95 | private Node ptr; 96 | private int remains; 97 | public dequeIterator() { 98 | ptr = guard.next; 99 | remains = size; 100 | } 101 | 102 | @Override 103 | public Item next() { 104 | if (remains == 0) { 105 | throw new NoSuchElementException(); 106 | } 107 | Item retValue = ptr.value; 108 | ptr = ptr.next; 109 | remains--; 110 | return retValue; 111 | } 112 | 113 | @Override 114 | public boolean hasNext() { 115 | return remains > 0; 116 | } 117 | 118 | @Override 119 | public void remove() { 120 | throw new UnsupportedOperationException("this deque implementation doesn't support remove in iterator"); 121 | } 122 | } 123 | // return an iterator over items in order from front to back 124 | public Iterator iterator() { 125 | return new dequeIterator(); 126 | } 127 | 128 | // unit testing (required) 129 | public static void main(String[] args) { 130 | Deque dq = new Deque<>(); 131 | for (int i = 0; i < 5; i++) { 132 | dq.addFirst("A" + i); 133 | } 134 | for (int i = 0; i < 5; i++) { 135 | dq.addLast("B" + i); 136 | } 137 | for (String s : dq) { 138 | System.out.println(s); 139 | } 140 | System.out.println("dq has " + dq.size() + " elements in total"); 141 | for (int i = 0; i < 10; i++) { 142 | System.out.println(dq.removeFirst()); 143 | System.out.println(dq.removeLast()); 144 | System.out.println(dq.size()); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /projects/queues/Permutation.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.StdIn; 8 | 9 | public class Permutation { 10 | public static void main(String[] args) { 11 | if (args.length != 1) { 12 | System.out.println("Usage: java Permutation number"); 13 | } 14 | RandomizedQueue rq = new RandomizedQueue<>(); 15 | while (!StdIn.isEmpty()) { 16 | rq.enqueue(StdIn.readString()); 17 | } 18 | int k = Integer.parseInt(args[0]); 19 | for (int i = 0; i < k; i++) { 20 | System.out.println(rq.dequeue()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /projects/queues/RandomizedQueue.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: 3 | * Date: 4 | * Description: 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.StdRandom; 8 | 9 | import java.util.Iterator; 10 | import java.util.NoSuchElementException; 11 | 12 | public class RandomizedQueue implements Iterable { 13 | 14 | private Item[] array; 15 | private int size; 16 | private int capacity; 17 | private int originalSize = 8; 18 | private double ratio = 0.25; 19 | 20 | // construct an empty randomized queue 21 | public RandomizedQueue() { 22 | array = (Item[]) new Object[originalSize]; 23 | size = 0; 24 | capacity = originalSize; 25 | } 26 | 27 | // is the randomized queue empty? 28 | public boolean isEmpty() { 29 | return size == 0; 30 | } 31 | 32 | // return the number of items on the randomized queue 33 | public int size() { 34 | return size; 35 | } 36 | 37 | private void resize(int newSize) { 38 | Item[] newArray = (Item[]) new Object[newSize]; 39 | for (int i = 0; i < size; i++) { 40 | newArray[i] = array[i]; 41 | } 42 | array = newArray; 43 | capacity = newSize; 44 | } 45 | // add the item 46 | public void enqueue(Item item) { 47 | if (item == null) { 48 | throw new IllegalArgumentException("cannot add null into a randomizedQueue"); 49 | } 50 | if (size == capacity) { 51 | resize(capacity * 2); 52 | } 53 | array[size++] = item; 54 | } 55 | 56 | // remove and return a random item 57 | public Item dequeue() { 58 | if (isEmpty()) { 59 | throw new NoSuchElementException("the queue is empty"); 60 | } 61 | int idx = StdRandom.uniform(size); 62 | Item retValue = array[idx]; 63 | array[idx] = array[size - 1]; 64 | array[size - 1] = null; 65 | size--; 66 | if (size > 0 && (double)size / capacity <= ratio) { 67 | resize(capacity / 2); 68 | } 69 | return retValue; 70 | } 71 | 72 | // return a random item (but do not remove it) 73 | public Item sample() { 74 | if (isEmpty()) { 75 | throw new NoSuchElementException("the queue is empty"); 76 | } 77 | int idx = StdRandom.uniform(size); 78 | return array[idx]; 79 | } 80 | 81 | private class RandomizedQueueIterator implements Iterator { 82 | private Item[] copyArray; 83 | private int remain; 84 | public RandomizedQueueIterator() { 85 | copyArray = (Item[]) new Object[size]; 86 | for (int i = 0; i < size; i++) { 87 | copyArray[i] = array[i]; 88 | } 89 | StdRandom.shuffle(copyArray); 90 | remain = size; 91 | } 92 | 93 | @Override 94 | public Item next() { 95 | if (remain == 0) { 96 | throw new NoSuchElementException(); 97 | } 98 | return copyArray[--remain]; 99 | } 100 | 101 | @Override 102 | public boolean hasNext() { 103 | return remain != 0; 104 | } 105 | 106 | @Override 107 | public void remove() { 108 | throw new UnsupportedOperationException(); 109 | } 110 | } 111 | // return an independent iterator over items in random order 112 | public Iterator iterator() { 113 | return new RandomizedQueueIterator(); 114 | } 115 | 116 | // unit testing (required) 117 | public static void main(String[] args) { 118 | RandomizedQueue rq = new RandomizedQueue<>(); 119 | for (int i = 0; i < 18; i++) { 120 | rq.enqueue("A" + i); 121 | } 122 | System.out.println("first iterator"); 123 | for (String s : rq) { 124 | System.out.print(s + " "); 125 | } 126 | System.out.println(); 127 | System.out.println("second iterator "); 128 | for (String s : rq) { 129 | System.out.print(s + " "); 130 | } 131 | System.out.println(); 132 | for (int i = 0; i < 18; i++) { 133 | System.out.print("deque "); 134 | System.out.print(rq.dequeue()); 135 | System.out.println(". remain " + rq.size() + " elements. now capacity "); 136 | } 137 | 138 | } 139 | 140 | } 141 | 142 | -------------------------------------------------------------------------------- /projects/wordnet/Outcast.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.In; 2 | import edu.princeton.cs.algs4.StdOut; 3 | 4 | public class Outcast { 5 | private final WordNet wn; 6 | // constructor takes a WordNet object 7 | public Outcast(WordNet wordnet) { 8 | wn = wordnet; 9 | } 10 | 11 | // given an array of WordNet nouns, return an outcast 12 | public String outcast(String[] nouns) { 13 | int[] distances = new int[nouns.length]; 14 | for (int i = 0; i < nouns.length; i++) { 15 | for (int j = 0; j < nouns.length; j++) { 16 | if (j == i) { 17 | continue; 18 | } 19 | distances[i] += wn.distance(nouns[i], nouns[j]); 20 | } 21 | } 22 | int idx = 0; 23 | int maximum = distances[0]; 24 | for (int i = 1; i < distances.length; i++) { 25 | if (distances[i] > maximum) { 26 | idx = i; 27 | maximum = distances[i]; 28 | } 29 | } 30 | return nouns[idx]; 31 | } 32 | 33 | // client routine 34 | public static void main(String[] args) { 35 | WordNet wordnet = new WordNet(args[0], args[1]); 36 | Outcast outcast = new Outcast(wordnet); 37 | for (int t = 2; t < args.length; t++) { 38 | In in = new In(args[t]); 39 | String[] nouns = in.readAllStrings(); 40 | StdOut.println(args[t] + ": " + outcast.outcast(nouns)); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /projects/wordnet/SAP.java: -------------------------------------------------------------------------------- 1 | import edu.princeton.cs.algs4.BreadthFirstDirectedPaths; 2 | import edu.princeton.cs.algs4.Digraph; 3 | import edu.princeton.cs.algs4.In; 4 | import edu.princeton.cs.algs4.StdIn; 5 | import edu.princeton.cs.algs4.StdOut; 6 | import java.util.Iterator; 7 | 8 | public class SAP { 9 | // constructor takes a digraph (not necessarily a DAG) 10 | private final Digraph diG; 11 | public SAP(Digraph G) { 12 | diG = new Digraph(G); 13 | } 14 | 15 | // length of shortest ancestral path between v and w; -1 if no such path 16 | public int length(int v, int w) { 17 | BreadthFirstDirectedPaths bfdp1 = new BreadthFirstDirectedPaths(diG, v); 18 | BreadthFirstDirectedPaths bfdp2 = new BreadthFirstDirectedPaths(diG, w); 19 | int vertices = diG.V(); 20 | int minPath = Integer.MAX_VALUE; 21 | for (int i = 0; i < vertices; i++) { 22 | if (bfdp1.hasPathTo(i) && bfdp2.hasPathTo(i)) { 23 | minPath = Math.min(bfdp1.distTo(i) + bfdp2.distTo(i), minPath); 24 | } 25 | } 26 | return minPath == Integer.MAX_VALUE ? -1 : minPath; 27 | } 28 | 29 | // a common ancestor of v and w that participates in a shortest ancestral path; -1 if no such path 30 | public int ancestor(int v, int w) { 31 | BreadthFirstDirectedPaths bfdp1 = new BreadthFirstDirectedPaths(diG, v); 32 | BreadthFirstDirectedPaths bfdp2 = new BreadthFirstDirectedPaths(diG, w); 33 | int vertices = diG.V(); 34 | int minPath = diG.V(); 35 | int commonAncestor = -1; 36 | for (int i = 0; i < vertices; i++) { 37 | if (bfdp1.hasPathTo(i) && bfdp2.hasPathTo(i)) { 38 | int currentPath = bfdp1.distTo(i) + bfdp2.distTo(i); 39 | if (currentPath < minPath) { 40 | minPath = currentPath; 41 | commonAncestor = i; 42 | } 43 | } 44 | } 45 | return commonAncestor; 46 | 47 | } 48 | 49 | private boolean hasValue(Iterable a) { 50 | Iterator it = a.iterator(); 51 | return it.hasNext(); 52 | } 53 | // length of shortest ancestral path between any vertex in v and any vertex in w; -1 if no such path 54 | public int length(Iterable v, Iterable w) { 55 | if (v == null || w == null) { 56 | throw new IllegalArgumentException("variable can not be null"); 57 | } 58 | if (!hasValue(v) || !hasValue(w)) { 59 | return -1; 60 | } 61 | BreadthFirstDirectedPaths bfdp1 = new BreadthFirstDirectedPaths(diG, v); 62 | BreadthFirstDirectedPaths bfdp2 = new BreadthFirstDirectedPaths(diG, w); 63 | 64 | int vertices = diG.V(); 65 | int minPath = Integer.MAX_VALUE; 66 | for (int i = 0; i < vertices; i++) { 67 | if (bfdp1.hasPathTo(i) && bfdp2.hasPathTo(i)) { 68 | minPath = Math.min(bfdp1.distTo(i) + bfdp2.distTo(i), minPath); 69 | } 70 | } 71 | return minPath == Integer.MAX_VALUE ? -1 : minPath; 72 | } 73 | 74 | // a common ancestor that participates in shortest ancestral path; -1 if no such path 75 | public int ancestor(Iterable v, Iterable w) { 76 | if (v == null || w == null) { 77 | throw new IllegalArgumentException("variable can not be null"); 78 | } 79 | if (!hasValue(v) || !hasValue(w)) { 80 | return -1; 81 | } 82 | BreadthFirstDirectedPaths bfdp1 = new BreadthFirstDirectedPaths(diG, v); 83 | BreadthFirstDirectedPaths bfdp2 = new BreadthFirstDirectedPaths(diG, w); 84 | int vertices = diG.V(); 85 | int minPath = diG.V(); 86 | int commonAncestor = -1; 87 | for (int i = 0; i < vertices; i++) { 88 | if (bfdp1.hasPathTo(i) && bfdp2.hasPathTo(i)) { 89 | int currentPath = bfdp1.distTo(i) + bfdp2.distTo(i); 90 | if (currentPath < minPath) { 91 | minPath = currentPath; 92 | commonAncestor = i; 93 | } 94 | } 95 | } 96 | return commonAncestor; 97 | } 98 | 99 | // do unit testing of this class 100 | public static void main(String[] args) { 101 | In in = new In(args[0]); 102 | Digraph G = new Digraph(in); 103 | SAP sap = new SAP(G); 104 | while (!StdIn.isEmpty()) { 105 | int v = StdIn.readInt(); 106 | int w = StdIn.readInt(); 107 | int length = sap.length(v, w); 108 | int ancestor = sap.ancestor(v, w); 109 | StdOut.printf("length = %d, ancestor = %d\n", length, ancestor); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /projects/wordnet/WordNet.java: -------------------------------------------------------------------------------- 1 | /* ***************************************************************************** 2 | * Name: FlyingPig 3 | * Date: 2021.3.10. 4 | * Description: Word Net project 5 | **************************************************************************** */ 6 | 7 | import edu.princeton.cs.algs4.Digraph; 8 | import edu.princeton.cs.algs4.DirectedCycle; 9 | 10 | import edu.princeton.cs.algs4.In; 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.HashSet; 14 | import java.util.Map; 15 | import java.util.Set; 16 | 17 | public class WordNet { 18 | private final ArrayList> synsets; 19 | private final Map> nounToSynset; 20 | private final ArrayList oriSynsets; 21 | private final Digraph wordNet; 22 | private final int n; // number of synsets 23 | private final SAP sapCounter; 24 | // constructor takes the name of the two input files 25 | public WordNet(String synsetsFile, String hypernymsFile) { 26 | if (synsetsFile == null || hypernymsFile == null) { 27 | throw new IllegalArgumentException("argument for constructor can not be null"); 28 | } 29 | synsets = new ArrayList<>(); 30 | nounToSynset = new HashMap<>(); 31 | oriSynsets = new ArrayList<>(); 32 | readSynsets(synsetsFile); 33 | n = synsets.size(); 34 | wordNet = new Digraph(n); 35 | readHypernyms(hypernymsFile); 36 | hasCycle(); 37 | hasRoots(); 38 | sapCounter = new SAP(wordNet); 39 | } 40 | 41 | private void hasCycle() { 42 | DirectedCycle cycle = new DirectedCycle(wordNet); 43 | if (cycle.hasCycle()) { 44 | throw new IllegalArgumentException("word net should not have a cycle in it"); 45 | } 46 | } 47 | 48 | private void hasRoots() { 49 | int roots = 0; 50 | for (int i = 0; i < n; i++) { 51 | if (wordNet.outdegree(i) == 0) { 52 | roots++; 53 | if (roots >= 2) { 54 | throw new IllegalArgumentException("word net should not have more than one root"); 55 | } 56 | } 57 | } 58 | } 59 | 60 | // read in synsets 61 | private void readSynsets(String synsetsFile) { 62 | In in = new In(synsetsFile); 63 | String[] fields; 64 | while (!in.isEmpty()) { 65 | fields = in.readLine().split(","); 66 | oriSynsets.add(fields[1]); 67 | Set tmp = new HashSet<>(); 68 | for (String s : fields[1].split(" ")) { 69 | tmp.add(s); 70 | if (!nounToSynset.containsKey(s)) { 71 | Set newNoun = new HashSet<>(); 72 | newNoun.add(Integer.parseInt(fields[0])); 73 | nounToSynset.put(s, newNoun); 74 | } else { 75 | Set oldNoun = nounToSynset.get(s); 76 | oldNoun.add(Integer.parseInt(fields[0])); 77 | } 78 | } 79 | synsets.add(tmp); 80 | } 81 | } 82 | 83 | // read in hypernyms 84 | private void readHypernyms(String hypernymsFile) { 85 | In in = new In(hypernymsFile); 86 | String[] fields; 87 | while (!in.isEmpty()) { 88 | fields = in.readLine().split(","); 89 | int v = Integer.parseInt(fields[0]); 90 | for (int i = 1; i < fields.length; i++) { 91 | int w = Integer.parseInt(fields[i]); 92 | wordNet.addEdge(v, w); 93 | } 94 | } 95 | } 96 | 97 | // returns all WordNet nouns 98 | public Iterable nouns() { 99 | return nounToSynset.keySet(); 100 | } 101 | 102 | // is the word a WordNet noun? 103 | public boolean isNoun(String word) { 104 | if (word == null) { 105 | throw new IllegalArgumentException("word can not be null"); 106 | } 107 | return nounToSynset.containsKey(word); 108 | } 109 | 110 | // distance between nounA and nounB (defined below) 111 | public int distance(String nounA, String nounB) { 112 | if (!isNoun(nounA) || !isNoun(nounB)) { 113 | throw new IllegalArgumentException("noun is not in the word net"); 114 | } 115 | return sapCounter.length(nounToSynset.get(nounA), nounToSynset.get(nounB)); 116 | } 117 | 118 | // a synset (second field of synsets.txt) that is the common ancestor of nounA and nounB 119 | // in a shortest ancestral path (defined below) 120 | public String sap(String nounA, String nounB) { 121 | if (!isNoun(nounA) || !isNoun(nounB)) { 122 | throw new IllegalArgumentException("noun is not in the word net"); 123 | } 124 | return oriSynsets.get(sapCounter.ancestor(nounToSynset.get(nounA), nounToSynset.get(nounB))); 125 | } 126 | 127 | // do unit testing of this class 128 | public static void main(String[] args) { 129 | return; 130 | } 131 | } 132 | --------------------------------------------------------------------------------