├── assignments ├── 8puzzle │ ├── instruction.md │ ├── Solver.java │ └── Board.java ├── Boggle │ ├── instruction.md │ ├── BoggleBoard.java │ └── BoggleSolver.java ├── baseball │ ├── instruction.md │ └── BaseballElimination.java ├── kdtrees │ ├── instruction.md │ ├── PointSet.java │ ├── NearestNeighborVisualizer.java │ ├── RectHV.java │ ├── RangeSearchVisualizer.java │ └── KdTree.java ├── percolation │ ├── instruction.md │ ├── PercolationSim.java │ ├── PercolationStats.java │ └── Percolation.java ├── randomizedQueues │ ├── instruction.md │ ├── Subset.java │ ├── RandomizedQueue.java │ └── Deque.java ├── burrowswheeler │ ├── instruction.md │ ├── CircularSuffixArray.java │ ├── BurrowsWheeler.java │ └── MoveToFront.java ├── seamcarving │ ├── instruction.md │ ├── ShowEnergy.java │ ├── PrintEnergy.java │ ├── ResizeDemo.java │ ├── ShowSeams.java │ ├── PrintSeams.java │ ├── SCUtility.java │ └── SeamCarver.java ├── collinearPoints │ ├── instruction.md │ ├── Brute.java │ ├── Fast.java │ └── Point.java └── wordnet │ ├── instruction.md │ ├── Outcast.java │ ├── SAP.java │ └── WordNet.java ├── README.md └── jobinterviewquestions ├── HashTables.java ├── DataCompression.java ├── MaxFlow.java ├── Tries.java ├── ShortestPaths.java ├── MSTs.java ├── RegularExpressions.java ├── UndirectedGraph.java ├── AnalysisofAlgorithms.java ├── ElementarySymbolTables.java ├── ElementarySorts.java ├── BalancedSearchTrees.java ├── Mergesort.java ├── DirectedGraph.java ├── PriorityQueue.java ├── QuickSort.java ├── SubstringSearch.java ├── StackandQueues.java ├── RadixSorts.java └── UnionFind.java /assignments/8puzzle/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for PQ and Symbol table 2 | 3 | http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 4 | -------------------------------------------------------------------------------- /assignments/Boggle/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for Tries and substring search 2 | http://coursera.cs.princeton.edu/algs4/assignments/boggle.html 3 | -------------------------------------------------------------------------------- /assignments/baseball/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for Max flow and Radix sort 2 | http://coursera.cs.princeton.edu/algs4/assignments/baseball.html 3 | -------------------------------------------------------------------------------- /assignments/kdtrees/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for balanced search trees 2 | 3 | http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 4 | -------------------------------------------------------------------------------- /assignments/percolation/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for UnionFind 2 | 3 | http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 4 | -------------------------------------------------------------------------------- /assignments/randomizedQueues/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for Stack and Queue 2 | http://coursera.cs.princeton.edu/algs4/assignments/queues.html 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algs4 2 | Coursera course: Algorithms 3 | 4 | http://algs4.cs.princeton.edu/ 5 | 6 | Programming Assignments & Job Interview Questions 7 | -------------------------------------------------------------------------------- /assignments/burrowswheeler/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for Regex and Data compression 2 | http://coursera.cs.princeton.edu/algs4/assignments/burrows.html 3 | -------------------------------------------------------------------------------- /assignments/seamcarving/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for MST and shortest paths 2 | 3 | http://coursera.cs.princeton.edu/algs4/assignments/seamCarving.html 4 | -------------------------------------------------------------------------------- /assignments/collinearPoints/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for MergeSort and QuickSort 2 | 3 | http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 4 | -------------------------------------------------------------------------------- /assignments/wordnet/instruction.md: -------------------------------------------------------------------------------- 1 | #Assignment for undirected graph and directed graph 2 | 3 | http://coursera.cs.princeton.edu/algs4/assignments/wordnet.html 4 | -------------------------------------------------------------------------------- /assignments/seamcarving/ShowEnergy.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.Picture; 4 | 5 | /** 6 | * Created by Leon on 8/9/15. 7 | */ 8 | public class ShowEnergy { 9 | public static void main(String[] args) 10 | { 11 | Picture inputImg = new Picture("./resources/seamCarving/7x3.png"); 12 | System.out.printf("image is %d columns by %d rows\n", inputImg.width(), inputImg.height()); 13 | //inputImg.show(); 14 | SeamCarver sc = new SeamCarver(inputImg); 15 | 16 | System.out.printf("Displaying energy calculated for each pixel.\n"); 17 | SeamCarver.printEnergy(sc); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /assignments/seamcarving/PrintEnergy.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.Picture; 4 | 5 | /** 6 | * Created by Leon on 8/9/15. 7 | */ 8 | public class PrintEnergy { 9 | public static void main(String[] args) 10 | { 11 | Picture inputImg = new Picture(args[0]); 12 | System.out.printf("image is %d pixels wide by %d pixels high.\n", inputImg.width(), inputImg.height()); 13 | 14 | SeamCarver sc = new SeamCarver(inputImg); 15 | 16 | System.out.printf("Printing energy calculated for each pixel.\n"); 17 | 18 | for (int j = 0; j < sc.height(); j++) 19 | { 20 | for (int i = 0; i < sc.width(); i++) 21 | System.out.printf("%9.0f ", sc.energy(i, j)); 22 | 23 | System.out.println(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /assignments/randomizedQueues/Subset.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.StdIn; 4 | import stdlib.StdRandom; 5 | 6 | /** 7 | * Created by Leon on 7/7/15. 8 | */ 9 | public class Subset { 10 | public static void main(String[] args) { 11 | int k = Integer.parseInt(args[1]); 12 | int count = 0; 13 | RandomizedQueue input = new RandomizedQueue(); 14 | while (StdIn.hasNextChar()) { 15 | count++; 16 | if (input.size() <= k) { 17 | input.enqueue(StdIn.readString()); 18 | } 19 | else { 20 | int r = StdRandom.uniform(count); 21 | if (r < k) { 22 | input.dequeue(); 23 | input.enqueue(StdIn.readString()); 24 | } 25 | } 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /assignments/collinearPoints/Brute.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.StdIn; 4 | 5 | /** 6 | * Created by Leon on 7/15/15. 7 | */ 8 | public class Brute { 9 | public static void main(String[] args) { 10 | int[] input = StdIn.readAllInts(); 11 | 12 | Point[] p = new Point[input[0]]; 13 | 14 | for (int i = 0; i < input[0]; i++) { 15 | p[i] = new Point(input[i*2 + 1], input[i*2 + 2]); 16 | } 17 | 18 | // for (int i = 0; i < p.length; i++) { 19 | // System.out.println(p[i]); 20 | // } 21 | 22 | for (int i = 0; i < input[0] - 3; i++) { 23 | for (int j = i + 1; j < input[0] - 2; j++) { 24 | for (int k = j + 1; k < input[0] - 1; k++) { 25 | for (int l = k + 1; l < input[0]; l++) { 26 | if (p[i].slopeTo(p[j]) == p[i].slopeTo(p[k]) && p[i].slopeTo(p[j]) == p[i].slopeTo(p[l])) 27 | System.out.println(p[i].toString() + "->" + p[j].toString() + "->" + p[k].toString() + "->" + p[l].toString()); 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /assignments/percolation/PercolationSim.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | import stdlib.StdRandom; 3 | /** 4 | * Created by Leon on 5/25/15. 5 | */ 6 | public class PercolationSim { 7 | private Percolation perc; 8 | private int N; 9 | 10 | public PercolationSim(int n) throws IllegalArgumentException{ 11 | N = n; 12 | perc = new Percolation(N); 13 | } 14 | 15 | private void randomOpen(boolean print) { 16 | int i = StdRandom.uniform(N) + 1; 17 | int j = StdRandom.uniform(N) + 1; 18 | while (perc.isOpen(i, j)) { 19 | i = StdRandom.uniform(N) + 1; 20 | j = StdRandom.uniform(N) + 1; 21 | } 22 | if (print) System.out.println("Open " + i + "," + j); 23 | perc.open(i, j); 24 | } 25 | 26 | public void percolate(boolean print) { 27 | while (!perc.isPercolated()) { 28 | randomOpen(print); 29 | } 30 | } 31 | 32 | public double estimate(boolean print) { 33 | percolate(print); 34 | return (double)(perc.count()) / (double)(N * N); 35 | } 36 | 37 | public static void main(String[] args) { 38 | PercolationSim percsim = new PercolationSim(100); 39 | double result = percsim.estimate(true); 40 | System.out.println(result); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /assignments/percolation/PercolationStats.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | import stdlib.StdStats; 3 | /** 4 | * Created by Leon on 5/25/15. 5 | */ 6 | public class PercolationStats { 7 | private double[] results; 8 | 9 | public PercolationStats(int N, int T) throws IllegalArgumentException { 10 | if (T <= 0) throw new IllegalArgumentException("Please specify a positive integer to carry out the experiments!"); 11 | results = new double[T]; 12 | for (int i = 0; i < T; i++) { 13 | PercolationSim temp = new PercolationSim(N); 14 | results[i] = temp.estimate(false); 15 | } 16 | } 17 | 18 | public double mean() { 19 | return StdStats.mean(results); 20 | } 21 | 22 | public double stddev() { 23 | return StdStats.stddev(results); 24 | } 25 | 26 | public double confidenceLo() { 27 | return mean() - 1.96 * stddev() / Math.sqrt(results.length); 28 | } 29 | 30 | public double confidenceHi() { 31 | return mean() + 1.96 * stddev() / Math.sqrt(results.length); 32 | } 33 | 34 | public static void main(String[] args) { 35 | PercolationStats percstats = new PercolationStats(200, 100); 36 | System.out.println("mean: " + percstats.mean()); 37 | System.out.println("stddev: " + percstats.stddev()); 38 | System.out.println("95% CI: " + percstats.confidenceLo() + "," + percstats.confidenceHi()); 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /assignments/seamcarving/ResizeDemo.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Stopwatch; 4 | import stdlib.Picture; 5 | 6 | /** 7 | * Created by Leon on 8/9/15. 8 | */ 9 | public class ResizeDemo { 10 | public static void main(String[] args) 11 | { 12 | /*if (args.length != 3) 13 | { 14 | System.out.println("Usage:\njava ResizeDemo [image filename] [num cols to remove] [num rows to remove]"); 15 | return; 16 | } 17 | */ 18 | 19 | Picture inputImg = new Picture("./resources/seamCarving/chameleon.png"); 20 | int removeColumns = 100; 21 | int removeRows = 50; 22 | 23 | System.out.printf("image is %d columns by %d rows\n", inputImg.width(), inputImg.height()); 24 | SeamCarver sc = new SeamCarver(inputImg); 25 | 26 | Stopwatch sw = new Stopwatch(); 27 | 28 | for (int i = 0; i < removeRows; i++) { 29 | int[] horizontalSeam = sc.findHorizontalSeam(); 30 | sc.removeHorizontalSeam(horizontalSeam); 31 | } 32 | 33 | for (int i = 0; i < removeColumns; i++) { 34 | int[] verticalSeam = sc.findVerticalSeam(); 35 | sc.removeVerticalSeam(verticalSeam); 36 | } 37 | Picture outputImg = sc.picture(); 38 | 39 | System.out.printf("new image size is %d columns by %d rows\n", sc.width(), sc.height()); 40 | 41 | System.out.println("Resizing time: " + sw.elapsedTime() + " seconds."); 42 | 43 | inputImg = new SeamCarver(inputImg).picture(); 44 | inputImg.show(); 45 | outputImg.show(); 46 | 47 | //SeamCarver inputSC = new SeamCarver(inputImg); 48 | 49 | //SeamCarver.printEnergy(inputSC); 50 | //SeamCarver.printEnergy(sc); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /assignments/wordnet/Outcast.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.In; 4 | import stdlib.StdOut; 5 | 6 | /** 7 | * Created by Leon on 8/3/15. 8 | */ 9 | public class Outcast { 10 | private WordNet wordnet; 11 | // constructor takes a WordNet object 12 | public Outcast(WordNet wordnet) { 13 | this.wordnet = wordnet; 14 | } 15 | // given an array of WordNet nouns, return an outcast 16 | public String outcast(String[] nouns) { 17 | int d = 0; 18 | String outcast = nouns[0]; 19 | 20 | for (int i = 0; i < nouns.length; i++) { 21 | int tmp = distance(nouns[i], nouns); 22 | if (tmp > d) { 23 | d = tmp; 24 | outcast = nouns[i]; 25 | } 26 | } 27 | return outcast; 28 | } 29 | 30 | private int distance(String noun, String[] nouns) { 31 | int result = 0; 32 | 33 | for (int i = 0; i < nouns.length; i++) { 34 | result += wordnet.distance(noun, nouns[i]); 35 | } 36 | return result; 37 | } 38 | 39 | public static void main(String[] args) { 40 | String[] outcasts = new String[3]; 41 | outcasts[0] = "./resources/wordnet/outcast5.txt"; 42 | outcasts[1] = "./resources/wordnet/outcast8.txt"; 43 | outcasts[2] = "./resources/wordnet/outcast11.txt"; 44 | WordNet wordnet = new WordNet("./resources/wordnet/synsets.txt", "./resources/wordnet/hypernyms.txt"); 45 | Outcast outcast = new Outcast(wordnet); 46 | for (int t = 0; t < outcasts.length; t++) { 47 | In in = new In(outcasts[t]); 48 | String[] nouns = in.readAllStrings(); 49 | StdOut.println(outcasts[t] + ": " + outcast.outcast(nouns)); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /assignments/seamcarving/ShowSeams.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.Picture; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * Created by Leon on 8/9/15. 9 | */ 10 | public class ShowSeams { 11 | private static void showHorizontalSeam(SeamCarver sc) 12 | { 13 | Picture ep = SCUtility.toEnergyPicture(sc); 14 | int[] horizontalSeam = sc.findHorizontalSeam(); 15 | Picture epOverlay = SCUtility.seamOverlay(ep, true, horizontalSeam); 16 | epOverlay.show(); 17 | } 18 | 19 | 20 | private static void showVerticalSeam(SeamCarver sc) 21 | { 22 | Picture ep = SCUtility.toEnergyPicture(sc); 23 | int[] verticalSeam = sc.findVerticalSeam(); 24 | Picture epOverlay = SCUtility.seamOverlay(ep, false, verticalSeam); 25 | epOverlay.show(); 26 | } 27 | 28 | private static void printHorizontalSeam(SeamCarver sc) { 29 | int[] horizontalSeam = sc.findHorizontalSeam(); 30 | System.out.println(Arrays.toString(horizontalSeam)); 31 | } 32 | 33 | private static void printVerticalSeam(SeamCarver sc) { 34 | int[] verticalSeam = sc.findVerticalSeam(); 35 | System.out.println(Arrays.toString(verticalSeam)); 36 | } 37 | 38 | public static void main(String[] args) 39 | { 40 | Picture inputImg = new Picture("./resources/seamCarving/10x12.png"); 41 | System.out.printf("image is %d columns by %d rows\n", inputImg.width(), inputImg.height()); 42 | //inputImg.show(); 43 | SeamCarver sc = new SeamCarver(inputImg); 44 | 45 | SeamCarver.printEnergy(sc); 46 | 47 | System.out.println("Displaying horizontal seam calculated.\n"); 48 | printHorizontalSeam(sc); 49 | 50 | System.out.println("Displaying vertical seam calculated.\n"); 51 | printVerticalSeam(sc); 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /assignments/collinearPoints/Fast.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Queue; 4 | import stdlib.StdIn; 5 | 6 | import java.util.Arrays; 7 | 8 | /** 9 | * Created by Leon on 7/16/15. 10 | */ 11 | public class Fast { 12 | public static void main(String[] args) { 13 | int[] input = StdIn.readAllInts(); 14 | 15 | Point[] p = new Point[input[0]]; 16 | 17 | for (int i = 0; i < input[0]; i++) p[i] = new Point(input[i * 2 + 1], input[i * 2 + 2]); 18 | 19 | Queue slopes = new Queue(); 20 | 21 | for (int i = 0; i < input[0] - 3; i++) { 22 | Arrays.sort(p, i, input[0], p[i].SLOPE_ORDER); 23 | System.out.println(p[i]); 24 | int start = i + 1; 25 | while (start < p.length - 2) { 26 | int count = 1; 27 | int end = start + 1; 28 | double slope = p[i].slopeTo(p[start]); 29 | while (end < p.length && p[i].slopeTo(p[end]) == slope) { 30 | count++; 31 | end++; 32 | } 33 | //System.out.println(count); 34 | if (count >= 3) { 35 | boolean exist = false; 36 | for (Double s : slopes) { 37 | if (s == slope) { 38 | exist = true; 39 | break; 40 | } 41 | } 42 | if (!exist) { 43 | while (start < end) { 44 | System.out.print(p[start++] + "->"); 45 | } 46 | System.out.print(p[i]); 47 | System.out.println(""); 48 | slopes.enqueue(slope); 49 | } 50 | } 51 | start = end; 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /assignments/burrowswheeler/CircularSuffixArray.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | /** 4 | * Created by Leon on 8/24/15. 5 | */ 6 | public class CircularSuffixArray { 7 | private int[] indices; //indices to store the order of sorted circular suffixes 8 | private String s; 9 | private int N; 10 | private static final int R = 256; 11 | // circular suffix array of s 12 | public CircularSuffixArray(String s) { 13 | this.s = s; 14 | this.N = s.length(); 15 | initializeIndex(); 16 | sort(N); 17 | } 18 | //helper function to initialize circular suffixes indices 19 | private void initializeIndex() { 20 | indices = new int[N]; 21 | for (int i = 0; i < N; i++) { 22 | indices[i] = i; 23 | } 24 | } 25 | //helper function, radix sort 26 | private void sort(int W) { 27 | int[] aux = new int[N]; 28 | 29 | for (int d = W - 1; d >=0; d--) { 30 | int[] count = new int[R+1]; 31 | 32 | for (int i = 0; i < N; i++) { 33 | count[s.charAt((d + indices[i]) % N) + 1]++; 34 | } 35 | 36 | for (int r = 0; r < R; r++) { 37 | count[r + 1] += count[r]; 38 | } 39 | 40 | for (int i = 0; i < N; i++) { 41 | aux[count[s.charAt((d + indices[i]) % N)]++] = indices[i]; 42 | } 43 | 44 | for (int i = 0; i < N; i++) 45 | indices[i] = aux[i]; 46 | } 47 | } 48 | 49 | // length of s 50 | public int length() { 51 | return N; 52 | } 53 | 54 | // returns index of ith sorted suffix 55 | public int index(int i) { 56 | return indices[i]; 57 | } 58 | 59 | public static void main(String[] args) { 60 | CircularSuffixArray csa = new CircularSuffixArray("ABRACADABRA!"); 61 | for (int i = 0; i < csa.length(); i++) { 62 | System.out.println(csa.index(i)); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /jobinterviewquestions/HashTables.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | 4 | import algs4.Vector; 5 | 6 | import java.util.HashSet; 7 | 8 | /** 9 | * Created by Leon on 7/27/15. 10 | */ 11 | public class HashTables { 12 | /* 13 | Question 1 14 | 4-SUM. 15 | Given an array a[] of N integers, 16 | the 4-SUM problem is to determine if there exist distinct indices i, j, k, and l such that a[i]+a[j]=a[k]+a[l]. 17 | Design an algorithm for the 4-SUM problem that takes time proportional to N2 (under suitable technical assumptions). 18 | */ 19 | 20 | public static boolean fourSum(int[] a) { 21 | int n = a.length; 22 | assert n >= 4; 23 | HashSet s = new HashSet(); 24 | for (int i = 0; i < n; i++) { 25 | for (int j = i + 1; j < n; j++) { 26 | int tmp = a[i] + a[j]; 27 | if (s.contains(tmp)) { 28 | System.out.println(tmp); 29 | return true; 30 | } 31 | else s.add(tmp); 32 | } 33 | } 34 | return false; 35 | } 36 | 37 | /* 38 | Question 2 39 | Hashing with wrong hashCode() or equals(). 40 | Suppose that you implement a data type OlympicAthlete for use in a java.util.HashMap. 41 | Describe what happens if you override hashCode() but not equals(). 42 | Describe what happens if you override equals() but not hashCode(). 43 | Describe what happens if you override hashCode() but implement public boolean equals(OlympicAthlete that) 44 | instead of public boolean equals(Object that). 45 | */ 46 | 47 | /* 48 | 1. Same athelete will be hashed into one bucket, but you can't find the match through search 49 | 2. Same athelete will not be hashed into one bucket 50 | 3. 51 | */ 52 | 53 | public static void main(String[] args) { 54 | int[] a = {1,3,4,5,6,7,8,9}; 55 | System.out.println(fourSum(a)); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /assignments/kdtrees/PointSet.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Point2D; 4 | import algs4.Queue; 5 | import algs4.RedBlackBST; 6 | import org.omg.CORBA.PUBLIC_MEMBER; 7 | 8 | import java.util.TreeSet; 9 | 10 | /** 11 | * Created by Leon on 7/22/15. 12 | */ 13 | public class PointSet { 14 | private TreeSet points; 15 | 16 | public PointSet() { 17 | points = new TreeSet(); 18 | } 19 | 20 | public boolean isEmpty() { 21 | return points.isEmpty(); 22 | } 23 | 24 | public int size() { 25 | return points.size(); 26 | } 27 | 28 | public void insert(Point2D p) { 29 | if (p == null) throw new NullPointerException(); 30 | points.add(p); 31 | } 32 | 33 | public boolean contains(Point2D p) { 34 | if (p == null) throw new NullPointerException(); 35 | return points.contains(p); 36 | } 37 | 38 | public void draw() { 39 | if (isEmpty()) return; 40 | for (Point2D p : points) { 41 | p.draw(); 42 | } 43 | } 44 | 45 | public Iterable range(RectHV rect) { 46 | if (rect == null) throw new NullPointerException(); 47 | if (isEmpty()) return null; 48 | Queue inside = new Queue(); 49 | 50 | for (Point2D p : points) { 51 | if (rect.contains(p)) inside.enqueue(p); 52 | } 53 | 54 | if (inside.isEmpty()) return null; 55 | return inside; 56 | } 57 | 58 | public Point2D nearest(Point2D p) { 59 | if (p == null) throw new NullPointerException(); 60 | if (isEmpty()) return null; 61 | double min = Double.MAX_VALUE; 62 | Point2D nearest = p; 63 | 64 | for (Point2D point : points) { 65 | if (point.distanceSquaredTo(p) < min) { 66 | nearest = point; 67 | min = point.distanceSquaredTo(p); 68 | } 69 | } 70 | return nearest; 71 | } 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /assignments/burrowswheeler/BurrowsWheeler.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.BinaryStdIn; 4 | import stdlib.BinaryStdOut; 5 | import stdlib.StdIn; 6 | import stdlib.StdOut; 7 | 8 | /** 9 | * Created by Leon on 8/25/15. 10 | */ 11 | public class BurrowsWheeler { 12 | private static final int R = 256; 13 | // apply Burrows-Wheeler encoding, reading from standard input and writing to standard output 14 | public static void encode() { 15 | String s = BinaryStdIn.readString(); 16 | CircularSuffixArray csa = new CircularSuffixArray(s); 17 | int n = csa.length(); 18 | int m = s.length(); 19 | 20 | for (int i = 0; i < n; i++) { 21 | if (csa.index(i) == 0) { 22 | BinaryStdOut.write(i); 23 | break; 24 | } 25 | } 26 | 27 | for (int i = 0; i < n; i++) { 28 | int index = csa.index(i); 29 | BinaryStdOut.write(s.charAt((index + m) % m)); 30 | } 31 | BinaryStdOut.close(); 32 | } 33 | 34 | // apply Burrows-Wheeler decoding, reading from standard input and writing to standard output 35 | public static void decode() { 36 | int first = BinaryStdIn.readInt(); 37 | char[] t = BinaryStdIn.readString().toCharArray(); 38 | 39 | int[] count = new int[R+1]; 40 | int[] next = new int[t.length]; 41 | 42 | for (int i = 0; i < t.length; i++) 43 | count[t[i] + 1]++; 44 | 45 | for (int r = 0; r < R; r++) 46 | count[r+1] += count[r]; 47 | 48 | for (int i = 0; i < t.length; i++) 49 | next[count[t[i]]++] = i; 50 | 51 | int p = first; 52 | for (int i = 0; i < t.length; i++) { 53 | BinaryStdOut.write(t[p]); 54 | p = next[first]; 55 | } 56 | BinaryStdOut.close(); 57 | } 58 | 59 | // if args[0] is '-', apply Burrows-Wheeler encoding 60 | // if args[0] is '+', apply Burrows-Wheeler decoding 61 | public static void main(String[] args) { 62 | if (args[0].equals("-")) encode(); 63 | else if (args[0].equals("+")) decode(); 64 | else throw new IllegalArgumentException("Please use - and + to specify encoding or decoding!"); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /jobinterviewquestions/DataCompression.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | /** 4 | * Created by Leon on 8/23/15. 5 | */ 6 | public class DataCompression { 7 | /* 8 | Question 1 9 | Ternary Huffman codes. 10 | Generalize the Huffman algorithm to codewords over the ternary alphabet (0, 1, and 2) instead of the binary alphabet. 11 | That is, given a bytestream, find a prefix-free ternary code that uses as few trits (0s, 1s, and 2s) as possible. Prove that it yields optimal prefix-free ternary code. 12 | */ 13 | 14 | /* 15 | "Pick the smallest three frequencies, join them together and create 16 | a node with the frequency equal to the sum of the three. Repeat. However, 17 | notice that every contraction reduces the number of leaves by 2 – we remove 18 | 3 nodes and add 1 back. So to make sure that we end up with just one node, 19 | we have to have an odd number of nodes to start with. If not, add a dummy 20 | node with 0 frequency to start with." 21 | */ 22 | 23 | /* 24 | Question 2 25 | Uniquely decodable code. 26 | Identify an optimal uniquely-decodable code that is neither prefix free nor suffix tree. 27 | Identify two optimal prefix-free codes for the same input that have a different distribution of codeword lengths. 28 | */ 29 | 30 | 31 | /* 32 | Question 3 33 | Move-to-front coding. Design an algorithm to implement move-to-front encoding so that each operation takes logarithmic time in the worst case. 34 | That is, maintain alphabet of symbols in a list. 35 | A symbol is encoded as the number of symbols that precede it in the list. After encoding a symbol, move it to the front of the list. 36 | */ 37 | 38 | /* 39 | 1. Logarithmic time operation: use RedBlackBST in algs4, use rank to write the encoding, use delete and min to move the symbol to the front of the tree 40 | 2. Algorithm: 41 | initialize the symbol table; 42 | 43 | while ( not end-of-file ) { 44 | 45 | K = get character; 46 | 47 | output K’s position(P) in the symbol table; (use RedBlackBST.rank()) 48 | 49 | move K to front of the symbol table. (delete K, then get min() and add back K, set K's new value less than min()) 50 | 51 | } 52 | */ 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /assignments/seamcarving/PrintSeams.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.Picture; 4 | import stdlib.StdOut; 5 | 6 | /** 7 | * Created by Leon on 8/9/15. 8 | */ 9 | public class PrintSeams { 10 | private final static boolean HORIZONTAL = true; 11 | private final static boolean VERTICAL = false; 12 | 13 | private static void printSeam(SeamCarver carver, int[] seam, boolean direction) { 14 | double totalSeamEnergy = 0.0; 15 | 16 | for (int row = 0; row < carver.height(); row++) { 17 | for (int col = 0; col < carver.width(); col++) { 18 | double energy = carver.energy(col, row); 19 | String marker = " "; 20 | if ((direction == HORIZONTAL && row == seam[col]) 21 | || (direction == VERTICAL && col == seam[row])) { 22 | marker = "*"; 23 | totalSeamEnergy += energy; 24 | } 25 | StdOut.printf("%7.2f%s ", energy, marker); 26 | } 27 | StdOut.println(); 28 | } 29 | // StdOut.println(); 30 | StdOut.printf("Total energy = %f\n", totalSeamEnergy); 31 | StdOut.println(); 32 | StdOut.println(); 33 | } 34 | 35 | public static void main(String[] args) { 36 | Picture picture = new Picture(args[0]); 37 | StdOut.printf("%s (%d-by-%d image)\n", args[0], picture.width(), picture.height()); 38 | StdOut.println(); 39 | StdOut.println("The table gives the dual-gradient energies of each pixel."); 40 | StdOut.println("The asterisks denote a minimum energy vertical or horizontal seam."); 41 | StdOut.println(); 42 | 43 | SeamCarver carver = new SeamCarver(picture); 44 | 45 | StdOut.printf("Vertical seam: { "); 46 | int[] verticalSeam = carver.findVerticalSeam(); 47 | for (int x : verticalSeam) 48 | StdOut.print(x + " "); 49 | StdOut.println("}"); 50 | printSeam(carver, verticalSeam, VERTICAL); 51 | 52 | StdOut.printf("Horizontal seam: { "); 53 | int[] horizontalSeam = carver.findHorizontalSeam(); 54 | for (int y : horizontalSeam) 55 | StdOut.print(y + " "); 56 | StdOut.println("}"); 57 | printSeam(carver, horizontalSeam, HORIZONTAL); 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /jobinterviewquestions/MaxFlow.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | /** 4 | * Created by Leon on 8/12/15. 5 | */ 6 | public class MaxFlow { 7 | /* 8 | Question 1 9 | Fattest path. 10 | Given an edge-weighted digraph and two vertices s and t, 11 | design an ElogE algorithm to find a fattest path from s to t. 12 | The bottleneck capacity of a path is the minimum weight of an edge on the path. 13 | A fattest path is a path such that no other path has a higher bottleneck capacity. 14 | */ 15 | 16 | /* 17 | 1. Dijkstra algorithm with bottleneck (v -> w, bottleneck[w] < min(bottleneck[v], e(v, w))) instead of sum of distance, max PQ instead of min PQ 18 | Note: Not a ElogE algorithm 19 | 20 | */ 21 | 22 | /* 23 | Question 2 24 | Perfect matchings in k-regular bipartite graphs. 25 | Suppose that there are n men and n women at a dance and that each man knows exactly k women and each woman knows exactly k men (and relationships are mutual). 26 | Show that it is always possible to arrange a dance so that each man and woman are matched with someone they know. 27 | */ 28 | 29 | /* 30 | L:R vertices, add s and t and new edges for s to L and R to t, 31 | we can now send |L| units of flow from s to t by setting the flow to 1 for every new edge and to 1/k for every original edge. 32 | */ 33 | 34 | /* 35 | Question 3 36 | Maximum weight closure problem. 37 | A subset of vertices S in a digraph is closed if there are no edges pointing from S to a vertex outside S. 38 | Given a digraph with weights (positive or negative) on the vertices, find a closed subset of vertices of maximum total weight. 39 | */ 40 | 41 | /* 42 | From wiki: 43 | Adding two additional vertices s and t. 44 | For each vertex v with positive weight in G, the augmented graph H contains an edge from s to v with capacity equal to the weight of v, 45 | and for each vertex v with negative weight in G, the augmented graph H contains an edge from v to t whose capacity is the negation of the weight of v. 46 | All of the edges in G are given infinite capacity in H. 47 | 48 | A minimum cut separating s from t in this graph cannot have any edges of G passing in the forward direction across the cut: 49 | a cut with such an edge would have infinite capacity and would not be minimum. 50 | */ 51 | } 52 | -------------------------------------------------------------------------------- /assignments/kdtrees/NearestNeighborVisualizer.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Point2D; 4 | import stdlib.In; 5 | import stdlib.StdDraw; 6 | 7 | /** 8 | * Created by Leon on 7/23/15. 9 | */ 10 | public class NearestNeighborVisualizer { 11 | 12 | public static void main(String[] args) { 13 | //String filename = args[0]; 14 | In in = new In("./resources/kdtree/circle10000.txt"); 15 | 16 | StdDraw.show(0); 17 | 18 | // initialize the two data structures with point from standard input 19 | PointSet brute = new PointSet(); 20 | KdTree kdtree = new KdTree(); 21 | while (!in.isEmpty()) { 22 | double x = in.readDouble(); 23 | double y = in.readDouble(); 24 | Point2D p = new Point2D(x, y); 25 | kdtree.insert(p); 26 | brute.insert(p); 27 | } 28 | 29 | System.out.println(kdtree.contains(new Point2D(0.206107,0.904508))); 30 | 31 | double x = 0; 32 | double y = 0; 33 | 34 | while (true) { 35 | 36 | // the location (x, y) of the mouse 37 | if (StdDraw.mousePressed()) { 38 | x = StdDraw.mouseX(); 39 | y = StdDraw.mouseY(); 40 | } 41 | else { 42 | continue; 43 | } 44 | Point2D query = new Point2D(x, y); 45 | 46 | 47 | // draw all of the points 48 | StdDraw.clear(); 49 | StdDraw.setPenColor(StdDraw.BLACK); 50 | StdDraw.setPenRadius(.01); 51 | brute.draw(); 52 | 53 | StdDraw.setPenColor(StdDraw.GREEN); 54 | StdDraw.setPenRadius(.01); 55 | query.draw(); 56 | System.out.println(query); 57 | 58 | // draw in red the nearest neighbor (using brute-force algorithm) 59 | StdDraw.setPenRadius(.03); 60 | StdDraw.setPenColor(StdDraw.RED); 61 | brute.nearest(query).draw(); 62 | StdDraw.setPenRadius(.02); 63 | //System.out.println("brute:" + brute.nearest(query) + "dist:" + brute.nearest(query).distanceSquaredTo(query)); 64 | 65 | // draw in blue the nearest neighbor (using kd-tree algorithm) 66 | StdDraw.setPenColor(StdDraw.BLUE); 67 | kdtree.nearest(query).draw(); 68 | System.out.println(""); 69 | //System.out.println("kdtree:" + kdtree.nearest(query) + "dist:" + kdtree.nearest(query).distanceSquaredTo(query)); 70 | StdDraw.show(0); 71 | StdDraw.show(40); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /jobinterviewquestions/Tries.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | /** 4 | * Created by Leon on 8/18/15. 5 | */ 6 | public class Tries { 7 | /* 8 | Question 1 9 | Prefix free codes. 10 | In data compression, a set of binary strings is prefix free if no string is a prefix of another. 11 | For example, {01,10,0010,1111} is prefix free, but {01,10,0010,10100} is not because 10 is a prefix of 10100. 12 | Design an efficient algorithm to determine if a set of binary strings is prefix-free. 13 | The running time of your algorithm should be proportional the number of bits in all of the binary stings. 14 | */ 15 | static class Prefixfree { 16 | 17 | private Node root; 18 | private int N; 19 | 20 | private class Node { 21 | private Node[] next = new Node[2]; 22 | private boolean isString; 23 | } 24 | 25 | private Node add(Node x, String binary, int d) { 26 | if (x == null) x = new Node(); 27 | if (d == binary.length()) { 28 | if (x.next[0] != null || x.next[1] != null) throw new IllegalArgumentException("This input is a prefix of existing binary!"); 29 | x.isString = true; 30 | N++; 31 | } else { 32 | if (x.isString) throw new IllegalArgumentException("Prefix exists for this input!"); 33 | int c = (int)binary.charAt(d) - 48; 34 | x.next[c] = add(x.next[c], binary, d + 1); 35 | } 36 | return x; 37 | } 38 | 39 | public void add(String binary) { 40 | root = add(root, binary, 0); 41 | } 42 | 43 | public int size() { 44 | return N; 45 | } 46 | } 47 | 48 | /* 49 | Question 2 50 | Boggle. 51 | Boggle is a word game played on an 4-by-4 grid of tiles, where each tile contains one letter in the alphabet. 52 | The goal is to find all words in the dictionary that can be made by following a path of adjacent tiles (with no tile repeated), 53 | where two tiles are adjacent if they are horizontal, vertical, or diagonal neighbors. 54 | */ 55 | 56 | /* 57 | programming assignment 58 | */ 59 | 60 | /* 61 | Question 3 62 | Suffix trees. Learn about and implement suffix trees, the ultimate string searching data structure. 63 | */ 64 | 65 | public static void main(String[] args) { 66 | Prefixfree pf = new Prefixfree(); 67 | 68 | pf.add("0100"); 69 | pf.add("01"); 70 | 71 | pf.add("01"); 72 | pf.add("0100"); 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /assignments/randomizedQueues/RandomizedQueue.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.StdRandom; 4 | 5 | import java.util.Iterator; 6 | import java.util.NoSuchElementException; 7 | 8 | /** 9 | * Created by Leon on 7/6/15. 10 | */ 11 | public class RandomizedQueue implements Iterable { 12 | private int N; 13 | private Item[] q; 14 | 15 | public RandomizedQueue() { 16 | q = (Item[]) new Object[2]; 17 | N = 0; 18 | } 19 | 20 | public boolean isEmpty() { 21 | return N == 0; 22 | } 23 | 24 | public int size() { 25 | return N; 26 | } 27 | 28 | private void resize(int max) { 29 | assert max >= N; 30 | Item[] temp = (Item[]) new Object[max]; 31 | int k = 0; 32 | for (int i = 0; i < N; i++) { 33 | temp[i] = q[i]; 34 | } 35 | q = temp; 36 | } 37 | 38 | public void enqueue(Item item) { 39 | if (item == null) throw new NullPointerException(); 40 | if (N == q.length) resize(2*q.length); 41 | q[N++] = item; 42 | } 43 | 44 | private void swap(Item[] a, int i, int j) { 45 | Item tmp = a[i]; 46 | a[i] = a[j]; 47 | a[j] = tmp; 48 | } 49 | 50 | public Item dequeue() { 51 | if (isEmpty()) throw new NoSuchElementException(); 52 | int r = StdRandom.uniform(N); 53 | swap(q, r, N - 1); 54 | Item item = q[N - 1]; 55 | q[N - 1] = null; 56 | N--; 57 | if (N > 0 && N == q.length/4) resize(q.length/2); 58 | return item; 59 | } 60 | 61 | public Item sample() { 62 | if (isEmpty()) throw new NoSuchElementException(); 63 | int r = StdRandom.uniform(N); 64 | return q[r]; 65 | } // return (but do not remove) a random item 66 | 67 | public Iterator iterator() {return new ArrayIterator();} // return an independent iterator over items in random order 68 | 69 | private class ArrayIterator implements Iterator { 70 | private int i = 0; 71 | private Item[] temp; 72 | 73 | public ArrayIterator() { 74 | temp = (Item[]) new Object[N]; 75 | for (int i = 0; i < N; i++) { 76 | temp[i] = q[i]; 77 | } 78 | StdRandom.shuffle(temp); 79 | } 80 | 81 | public boolean hasNext() { return i < N; } 82 | 83 | public void remove() { throw new UnsupportedOperationException(); } 84 | 85 | public Item next() { 86 | if (!hasNext()) throw new NoSuchElementException(); 87 | Item item = temp[i++]; 88 | return item; 89 | } 90 | 91 | } 92 | 93 | public static void main(String[] args) { 94 | 95 | } // unit testing 96 | } 97 | -------------------------------------------------------------------------------- /assignments/collinearPoints/Point.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | /** 4 | * Created by Leon on 7/15/15. 5 | */ 6 | 7 | import algs4.DoublingRatio; 8 | import stdlib.StdDraw; 9 | 10 | import java.util.Arrays; 11 | import java.util.Comparator; 12 | 13 | public class Point implements Comparable { 14 | 15 | // compare points by slope 16 | public final Comparator SLOPE_ORDER = new LineOrder(); // YOUR DEFINITION HERE 17 | 18 | private final int x; // x coordinate 19 | private final int y; // y coordinate 20 | 21 | // create the point (x, y) 22 | public Point(int x, int y) { 23 | /* DO NOT MODIFY */ 24 | this.x = x; 25 | this.y = y; 26 | } 27 | 28 | // plot this point to standard drawing 29 | public void draw() { 30 | /* DO NOT MODIFY */ 31 | StdDraw.point(x, y); 32 | } 33 | 34 | // draw line between this point and that point to standard drawing 35 | public void drawTo(Point that) { 36 | /* DO NOT MODIFY */ 37 | StdDraw.line(this.x, this.y, that.x, that.y); 38 | } 39 | 40 | // slope between this point and that point 41 | public double slopeTo(Point that) { 42 | /* YOUR CODE HERE */ 43 | if (compareTo(that) == 0) return Double.NEGATIVE_INFINITY; 44 | if (this.y == that.y) return 0.0; 45 | if (this.x == that.x) return Double.POSITIVE_INFINITY; 46 | return (double)(that.y - this.y) / (that.x - this.x); 47 | } 48 | 49 | // is this point lexicographically smaller than that one? 50 | // comparing y-coordinates and breaking ties by x-coordinates 51 | public int compareTo(Point that) { 52 | /* YOUR CODE HERE */ 53 | if (this.y < that.y) return -1; 54 | if (this.y > that.y) return 1; 55 | if (this.x < that.x) return -1; 56 | if (this.x > that.x) return 1; 57 | return 0; 58 | } 59 | 60 | // return string representation of this point 61 | public String toString() { 62 | /* DO NOT MODIFY */ 63 | return "(" + x + ", " + y + ")"; 64 | } 65 | 66 | private class LineOrder implements Comparator { 67 | public int compare(Point p, Point q) { 68 | if (slopeTo(p) < slopeTo(q)) return -1; 69 | if (slopeTo(p) > slopeTo(q)) return 1; 70 | return 0; 71 | } 72 | } 73 | 74 | // unit test 75 | public static void main(String[] args) { 76 | /* YOUR CODE HERE */ 77 | Point p0 = new Point(0, 0); 78 | Point p1 = new Point(5, 2); 79 | Point p2 = new Point(2, 1); 80 | Point[] p = new Point[3]; 81 | p[0] = p0; 82 | p[1] = p1; 83 | p[2] = p2; 84 | Arrays.sort(p); 85 | System.out.print(p1.slopeTo(p2)); 86 | 87 | } 88 | } -------------------------------------------------------------------------------- /assignments/percolation/Percolation.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | import algs4.WeightedQuickUnionUF; 3 | /** 4 | * Created by Leon on 5/25/15. 5 | */ 6 | public class Percolation { 7 | private WeightedQuickUnionUF grid; 8 | private boolean[] state; 9 | private int N; 10 | 11 | public Percolation(int n) throws IllegalArgumentException{ 12 | N = n; 13 | if(N <= 0) throw new IllegalArgumentException("Please specify a positive integer to initialize the grid!"); 14 | 15 | int gridN = N * N + 2; 16 | grid = new WeightedQuickUnionUF(gridN); 17 | state = new boolean[gridN]; 18 | 19 | for(int i = 1; i <= N; i++) { 20 | grid.union(0, i); 21 | grid.union(gridN - 1, gridN - 1 - i); 22 | } 23 | } 24 | 25 | private int getIndex(int i , int j) { 26 | return (i - 1) * N + j; 27 | } 28 | 29 | private void connectLeft(int index) { 30 | if(index % N == 1 || !state[index - 1]) return; 31 | else grid.union(index, index - 1); 32 | } 33 | 34 | private void connectRight(int index) { 35 | if(index % N == 0 || !state[index + 1]) return; 36 | else grid.union(index, index + 1); 37 | } 38 | 39 | private void connectUp(int index) { 40 | if(index <= N || !state[index - N]) return; 41 | else grid.union(index, index - N); 42 | } 43 | private void connectDown(int index) { 44 | if(index > N * N - N || !state[index + N]) return; 45 | else grid.union(index, index + N); 46 | } 47 | 48 | public void open(int i, int j) throws IndexOutOfBoundsException{ 49 | if (i < 1 || j < 1 || i > N || j > N) throw new IndexOutOfBoundsException("Grid is N by N!"); 50 | int index = getIndex(i, j); 51 | state[index] = true; 52 | connectLeft(index); 53 | connectRight(index); 54 | connectUp(index); 55 | connectDown(index); 56 | } 57 | 58 | public boolean isOpen(int i, int j) { 59 | int index = getIndex(i, j); 60 | return state[index]; 61 | } 62 | 63 | public boolean isFull(int i, int j) { 64 | int index = getIndex(i, j); 65 | return state[index] && grid.connected(index, 0); 66 | } 67 | public boolean isPercolated() { 68 | return grid.connected(0, state.length - 1); 69 | } 70 | 71 | public int count() { 72 | int c = 0; 73 | for (int i = 1; i <= N * N; i++) { 74 | if (state[i]) c += 1; 75 | } 76 | return c; 77 | } 78 | 79 | public static void main(String[] args) { 80 | Percolation perc = new Percolation(100); 81 | perc.open(1,1); 82 | perc.open(2,1); 83 | perc.open(3,2); 84 | perc.open(2,2); 85 | System.out.print(perc.isFull(3,2)); 86 | System.out.print(perc.count()); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /assignments/randomizedQueues/Deque.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | import java.util.NoSuchElementException; 6 | 7 | /** 8 | * Created by Leon on 7/6/15. 9 | */ 10 | public class Deque implements Iterable{ 11 | private int N; 12 | private Node first; 13 | private Node last; 14 | 15 | public Deque() { 16 | first = null; 17 | last = null; 18 | N = 0; 19 | } 20 | 21 | public boolean isEmpty() { 22 | return N == 0; 23 | } 24 | 25 | public int size() { 26 | return N; 27 | } 28 | 29 | public void addFirst(Item item) { 30 | if (item == null) throw new NullPointerException(); 31 | Node oldfirst = first; 32 | first = new Node(); 33 | first.item = item; 34 | first.next = oldfirst; 35 | if (isEmpty()) last = first; 36 | else oldfirst.previous = first; 37 | N++; 38 | } 39 | 40 | public void addLast(Item item) { 41 | if (item == null) throw new NullPointerException(); 42 | Node oldlast = last; 43 | last = new Node(); 44 | last.item = item; 45 | last.previous = oldlast; 46 | if (isEmpty()) first = last; 47 | else oldlast.next = last; 48 | N++; 49 | } 50 | 51 | public Item removeFirst() { 52 | if (isEmpty()) throw new NoSuchElementException(); 53 | Item item = first.item; 54 | first = first.next; 55 | N--; 56 | if (isEmpty()) last = null; 57 | else first.previous = null; 58 | return item; 59 | } 60 | 61 | public Item removeLast() { 62 | if (isEmpty()) throw new NoSuchElementException(); 63 | Item item = last.item; 64 | last = last.previous; 65 | N--; 66 | if (isEmpty()) first = null; 67 | else last.next = null; 68 | return item; 69 | } 70 | 71 | public Iterator iterator() { 72 | return new ListIterator(first); 73 | } 74 | 75 | private class ListIterator implements Iterator { 76 | private Node current; 77 | 78 | public ListIterator(Node first) {current = first;} 79 | public boolean hasNext() {return current != null;} 80 | public void remove() {throw new UnsupportedOperationException();} 81 | 82 | public Item next() { 83 | if (!hasNext()) throw new NoSuchElementException(); 84 | Item item = current.item; 85 | current = current.next; 86 | return item; 87 | } 88 | } 89 | 90 | private static class Node { 91 | private Item item; 92 | private Node next; 93 | private Node previous; 94 | } 95 | 96 | public static void main(String[] args) { 97 | 98 | } // unit testing 99 | } 100 | -------------------------------------------------------------------------------- /jobinterviewquestions/ShortestPaths.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.*; 4 | 5 | /** 6 | * Created by Leon on 8/5/15. 7 | */ 8 | public class ShortestPaths { 9 | /* 10 | Question 1 11 | Monotonic shortest path. 12 | Given an edge-weighted digraph G, 13 | design an ElogE algorithm to find a monotonic shortest path from s to every other vertex. 14 | A path is monotonic if the sequence of edge weights along the path are either strictly increasing or strictly decreasing. 15 | */ 16 | private DirectedEdge[] edgeTo; 17 | private double[] distTo; 18 | private IndexMinPQ pq; 19 | 20 | /* 21 | 1. Sort edges of each vertex, ascending or descending 22 | 2. relax edges using Dijkstra algorithm, check monotonic condition before check distTo 23 | */ 24 | 25 | /* 26 | Question 2 27 | Critical edge. 28 | Given an edge-weighted digraph, 29 | design an ElogV algorithm to find an edge whose removal causes the maximal increase (possibly infinite) in the length of the shortest path from s to t. 30 | Assume all of the edge weights are strictly positive. 31 | */ 32 | 33 | /* 34 | 1. remove the last edge before t, and run shortest path from s to t, find the change in distance, if infinite return 35 | 2. compare the new path with the original one, and find the last common vertex, use that as new t, repeat 1, 2 36 | 3. when reach s, compare all the distance changes by removals, decide which is the critical one 37 | */ 38 | 39 | /* 40 | Question 3 41 | Shortest path with one skippable edge. 42 | Given an edge-weighted digraph, 43 | design an ElogV algorithm to find a shortest path from s to t 44 | where you can change the weight of any one edge to zero. Assume the edge weights are nonnegative. 45 | */ 46 | 47 | //1. add reverse method in EdgeWeightedDigraph class 48 | public Iterable skippablePath(EdgeWeightedDigraph G,int s, int t) { 49 | DijkstraSP spaths = new DijkstraSP(G, s); 50 | DijkstraSP tpaths = new DijkstraSP(G.reverse(), t); 51 | 52 | double min = Double.MAX_VALUE; 53 | DirectedEdge skippable = null; 54 | 55 | for (DirectedEdge e : G.edges()) { 56 | int v = e.from(); 57 | int w = e.to(); 58 | if (spaths.distTo(v) + tpaths.distTo(w) < min) { 59 | skippable = e; 60 | min = spaths.distTo(v) + tpaths.distTo(w); 61 | } 62 | } 63 | 64 | Stack skippablepath = new Stack(); 65 | Stack tmp = new Stack(); 66 | 67 | for (DirectedEdge e : tpaths.pathTo(skippable.to())) skippablepath.push(e); 68 | skippablepath.push(skippable); 69 | for (DirectedEdge e : spaths.pathTo(skippable.from())) tmp.push(e); 70 | for (DirectedEdge e : tmp) skippablepath.push(e); 71 | return skippablepath; 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /jobinterviewquestions/MSTs.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.*; 4 | import com.sun.corba.se.impl.activation.ServerTableEntry; 5 | 6 | /** 7 | * Created by Leon on 8/5/15. 8 | */ 9 | public class MSTs { 10 | /* 11 | Question 1 12 | Bottleneck minimum spanning tree. 13 | Given a connected edge-weighted graph, 14 | design an efficient algorithm to find a minimum bottleneck spanning tree. 15 | The bottleneck capacity of a spanning tree is the weights of its largest edge. 16 | A minimum bottleneck spanning tree is a spanning tree of minimum bottleneck capacity. 17 | */ 18 | 19 | /* 20 | Can use any algorithm that help building a MST or: 21 | Camerini's algorithm: 22 | 1. Find the median edge weight W (find kth algorithm, use pivot and recursively find kth) 23 | 2. two subgraph by the median edge, 24 | if the lower part connected (using DFS or BFS), then decrease W and repeat 1, 2 25 | if the not connected, let the connected component become one node, increase W, repeat 1, 2 26 | */ 27 | 28 | /* 29 | Question 2 30 | Is an edge in a MST. 31 | Given an edge-weighted graph G and an edge e, design a linear-time algorithm to determine whether e appears in some MST of G. 32 | Note: Since your algorithm must take linear time in the worst case, you cannot afford to compute the MST itself. 33 | */ 34 | 35 | public boolean edgeInMST(EdgeWeightedGraph G, Edge e) { 36 | SET vertices = new SET(); 37 | double weight = e.weight(); 38 | for (Edge edge: G.edges()) { 39 | if (edge.weight() < weight) { 40 | int v = edge.either(); 41 | int w = edge.other(v); 42 | vertices.add(v); vertices.add(w); 43 | } 44 | } 45 | int v = e.either(); 46 | int w = e.other(v); 47 | if (vertices.contains(v) && vertices.contains(w)) return false; 48 | return true; 49 | } 50 | 51 | /* 52 | Question 3 53 | Minimum-weight feedback edge set. 54 | A feedback edge set of a graph is a subset of edges that contains at least one edge from every cycle in the graph. 55 | If the edges of a feedback edge set are removed, 56 | the resulting graph is acyclic. Given an edge-weighted graph, 57 | design an efficient algorithm to find a feedback edge set of minimum weight. Assume the edge weights are positive. 58 | */ 59 | 60 | /* 61 | use kruskal's algorithm, but use MaxPQ 62 | */ 63 | 64 | public Queue MFES(EdgeWeightedGraph G) { 65 | MaxPQ pq = new MaxPQ(); 66 | Queue mfes = new Queue(); 67 | int size = 0; 68 | 69 | for (Edge e : G.edges()) { 70 | pq.insert(e); 71 | } 72 | UF uf = new UF(G.V()); 73 | while (!pq.isEmpty()) { 74 | Edge e = pq.delMax(); 75 | int v = e.either(); 76 | int w = e.other(v); 77 | if (!uf.connected(v, w)) { 78 | uf.union(v, w); 79 | } 80 | else { 81 | mfes.enqueue(e); 82 | } 83 | } 84 | return mfes; 85 | 86 | } 87 | 88 | 89 | } 90 | -------------------------------------------------------------------------------- /assignments/kdtrees/RectHV.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Point2D; 4 | import stdlib.StdDraw; 5 | 6 | /** 7 | * Created by Leon on 7/22/15. 8 | */ 9 | public class RectHV { 10 | private final double xmin, ymin; // minimum x- and y-coordinates 11 | private final double xmax, ymax; // maximum x- and y-coordinates 12 | 13 | // construct the axis-aligned rectangle [xmin, xmax] x [ymin, ymax] 14 | public RectHV(double xmin, double ymin, double xmax, double ymax) { 15 | if (xmax < xmin || ymax < ymin) { 16 | throw new IllegalArgumentException("Invalid rectangle"); 17 | } 18 | this.xmin = xmin; 19 | this.ymin = ymin; 20 | this.xmax = xmax; 21 | this.ymax = ymax; 22 | } 23 | 24 | // accessor methods for 4 coordinates 25 | public double xmin() { return xmin; } 26 | public double ymin() { return ymin; } 27 | public double xmax() { return xmax; } 28 | public double ymax() { return ymax; } 29 | 30 | // width and height of rectangle 31 | public double width() { return xmax - xmin; } 32 | public double height() { return ymax - ymin; } 33 | 34 | // does this axis-aligned rectangle intersect that one? 35 | public boolean intersects(RectHV that) { 36 | return this.xmax >= that.xmin && this.ymax >= that.ymin 37 | && that.xmax >= this.xmin && that.ymax >= this.ymin; 38 | } 39 | 40 | // draw this axis-aligned rectangle 41 | public void draw() { 42 | StdDraw.line(xmin, ymin, xmax, ymin); 43 | StdDraw.line(xmax, ymin, xmax, ymax); 44 | StdDraw.line(xmax, ymax, xmin, ymax); 45 | StdDraw.line(xmin, ymax, xmin, ymin); 46 | } 47 | 48 | // distance from p to closest point on this axis-aligned rectangle 49 | public double distanceTo(Point2D p) { 50 | return Math.sqrt(this.distanceSquaredTo(p)); 51 | } 52 | 53 | // distance squared from p to closest point on this axis-aligned rectangle 54 | public double distanceSquaredTo(Point2D p) { 55 | double dx = 0.0, dy = 0.0; 56 | if (p.x() < xmin) dx = p.x() - xmin; 57 | else if (p.x() > xmax) dx = p.x() - xmax; 58 | if (p.y() < ymin) dy = p.y() - ymin; 59 | else if (p.y() > ymax) dy = p.y() - ymax; 60 | return dx*dx + dy*dy; 61 | } 62 | 63 | // does this axis-aligned rectangle contain p? 64 | public boolean contains(Point2D p) { 65 | return (p.x() >= xmin) && (p.x() <= xmax) 66 | && (p.y() >= ymin) && (p.y() <= ymax); 67 | } 68 | 69 | // are the two axis-aligned rectangles equal? 70 | public boolean equals(Object y) { 71 | if (y == this) return true; 72 | if (y == null) return false; 73 | if (y.getClass() != this.getClass()) return false; 74 | RectHV that = (RectHV) y; 75 | if (this.xmin != that.xmin) return false; 76 | if (this.ymin != that.ymin) return false; 77 | if (this.xmax != that.xmax) return false; 78 | if (this.ymax != that.ymax) return false; 79 | return true; 80 | } 81 | 82 | // return a string representation of this axis-aligned rectangle 83 | public String toString() { 84 | return "[" + xmin + ", " + xmax + "] x [" + ymin + ", " + ymax + "]"; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /assignments/kdtrees/RangeSearchVisualizer.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Point2D; 4 | import stdlib.In; 5 | import stdlib.StdDraw; 6 | 7 | /** 8 | * Created by Leon on 7/23/15. 9 | */ 10 | public class RangeSearchVisualizer { 11 | 12 | public static void main(String[] args) { 13 | 14 | //String filename = args[0]; 15 | In in = new In("./resources/kdtree/circle10000.txt"); 16 | 17 | // initialize the data structures with N points from standard input 18 | PointSet brute = new PointSet(); 19 | KdTree kdtree = new KdTree(); 20 | while (!in.isEmpty()) { 21 | double x = in.readDouble(); 22 | double y = in.readDouble(); 23 | Point2D p = new Point2D(x, y); 24 | kdtree.insert(p); 25 | brute.insert(p); 26 | } 27 | 28 | double x0 = 0.0, y0 = 0.0; // initial endpoint of rectangle 29 | double x1 = 0.5, y1 = 0.5; // current location of mouse 30 | boolean isDragging = false; // is the user dragging a rectangle 31 | 32 | //draw the points 33 | StdDraw.clear(); 34 | StdDraw.setPenColor(StdDraw.BLACK); 35 | StdDraw.setPenRadius(.01); 36 | brute.draw(); 37 | StdDraw.show(0); 38 | while (true) { 39 | StdDraw.show(40); 40 | //StdDraw.clear(); 41 | //System.out.println("start draw rect"); 42 | 43 | // user starts to drag a rectangle 44 | if (StdDraw.mousePressed() && !isDragging) { 45 | x0 = StdDraw.mouseX(); 46 | y0 = StdDraw.mouseY(); 47 | isDragging = true; 48 | continue; 49 | } 50 | 51 | // user is dragging a rectangle 52 | else if (StdDraw.mousePressed() && isDragging) { 53 | x1 = StdDraw.mouseX(); 54 | y1 = StdDraw.mouseY(); 55 | continue; 56 | } 57 | 58 | // mouse no longer pressed 59 | else if (!StdDraw.mousePressed() && isDragging) { 60 | isDragging = false; 61 | } 62 | 63 | else { 64 | continue; 65 | } 66 | 67 | //System.out.println(x0); 68 | //System.out.println(x1); 69 | 70 | 71 | RectHV rect = new RectHV(Math.min(x0, x1), Math.min(y0, y1), 72 | Math.max(x0, x1), Math.max(y0, y1)); 73 | //System.out.println("rect get"); 74 | // draw the points 75 | StdDraw.clear(); 76 | StdDraw.setPenColor(StdDraw.BLACK); 77 | StdDraw.setPenRadius(.01); 78 | brute.draw(); 79 | 80 | // draw the rectangle 81 | StdDraw.setPenColor(StdDraw.BLACK); 82 | StdDraw.setPenRadius(); 83 | rect.draw(); 84 | 85 | // draw the range search results for brute-force data structure in red 86 | StdDraw.setPenRadius(.03); 87 | StdDraw.setPenColor(StdDraw.RED); 88 | for (Point2D p : brute.range(rect)) 89 | p.draw(); 90 | 91 | // draw the range search results for kd-tree in blue 92 | StdDraw.setPenRadius(.02); 93 | StdDraw.setPenColor(StdDraw.BLUE); 94 | for (Point2D p : kdtree.range(rect)) 95 | p.draw(); 96 | 97 | StdDraw.show(40); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /jobinterviewquestions/RegularExpressions.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.Bag; 4 | import algs4.Digraph; 5 | import algs4.Stack; 6 | 7 | /** 8 | * Created by Leon on 8/23/15. 9 | */ 10 | public class RegularExpressions { 11 | /* 12 | Question 1 13 | Challenging REs. 14 | Construct a regular expression for each of the following languages over the binary alphabet or prove that no such regular expression is possible: 15 | All strings except 11 or 111. 16 | Strings with 1 in every odd-number bit position. 17 | Strings with an equal number of 0s and 1s. //impossible 18 | Strings with at least two 0s and at most one 1. 19 | Strings that when interpreted as a binary integer are a multiple of 3. 20 | Strings with no two consecutive 1s. 21 | Strings that are palindromes (same forwards and backwards). //impossible 22 | Strings with an equal number of substrings of the form 01 and 10. 23 | */ 24 | 25 | 26 | /* 27 | Question 2 28 | Exponential-size DFA. Design a regular expressions of length N such that any DFA that recognizes the same language has an exponential number of states. 29 | */ 30 | 31 | /* 32 | Question 3 33 | Extensions to NFA. Add to NFA.java the ability to handle multiway or, wildcard, and the + closure operator. 34 | */ 35 | 36 | /* 37 | make change to the constructor 38 | */ 39 | 40 | class NFA { 41 | private Digraph G; // digraph of epsilon transitions 42 | private String regexp; // regular expression 43 | private int M; // number of characters in regular expression 44 | 45 | // Create the algs4.NFA for the given RE 46 | public NFA(String regexp) { 47 | this.regexp = regexp; 48 | M = regexp.length(); 49 | Stack ops = new Stack(); 50 | G = new Digraph(M+1); 51 | for (int i = 0; i < M; i++) { 52 | int lp = i; 53 | if (regexp.charAt(i) == '(' || regexp.charAt(i) == '|') 54 | ops.push(i); 55 | else if (regexp.charAt(i) == ')') { 56 | int or = ops.pop(); 57 | 58 | // multiway or operator 59 | if (regexp.charAt(or) == '|') { 60 | Bag ors = new Bag(); 61 | while (ops.peek() == '|') { 62 | ors.add(ops.pop()); 63 | } 64 | lp = ops.pop(); 65 | for (int o : ors) { 66 | G.addEdge(lp, o + 1); 67 | G.addEdge(o, i); 68 | } 69 | } 70 | else if (regexp.charAt(or) == '(') 71 | lp = or; 72 | else assert false; 73 | } 74 | 75 | // closure operator (uses 1-character lookahead) 76 | if (i < M-1 && regexp.charAt(i+1) == '*') { 77 | G.addEdge(lp, i+1); 78 | G.addEdge(i+1, lp); 79 | } 80 | 81 | // + operator (uses 1-character lookahead) 82 | if (i < M-1 && regexp.charAt(i+1) == '+') { 83 | G.addEdge(i+1, lp); 84 | } 85 | 86 | if (regexp.charAt(i) == '(' || regexp.charAt(i) == '*' || regexp.charAt(i) == ')') 87 | G.addEdge(i, i+1); 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /jobinterviewquestions/UndirectedGraph.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.BreadthFirstPaths; 4 | import algs4.Graph; 5 | import algs4.Stack; 6 | 7 | import java.util.Iterator; 8 | 9 | /** 10 | * Created by Leon on 7/29/15. 11 | */ 12 | public class UndirectedGraph { 13 | private boolean[] marked; 14 | //private int[] edgeTo; 15 | 16 | public Iterator adj(int v) { 17 | return null; 18 | } 19 | 20 | /* 21 | Question 1 22 | Nonrecursive depth-first search. 23 | Implement depth-first search in an undirected graph without using recursion. 24 | */ 25 | 26 | private void dfs(UndirectedGraph G, int v) { 27 | marked[v] = true; 28 | Stack visited = new Stack(); 29 | visited.push(v); 30 | 31 | while (!visited.isEmpty()) { 32 | int tmp = visited.peek(); 33 | if (adj(tmp).hasNext()) { 34 | int w = adj(tmp).next(); 35 | if (!marked[w]) { 36 | marked[w] = true; 37 | visited.push(w); 38 | } 39 | } 40 | else { 41 | visited.pop(); 42 | } 43 | } 44 | 45 | } 46 | 47 | /* 48 | Question 2 49 | Diameter and center of a tree. Given a connected graph with no cycles 50 | Diameter: design a linear-time algorithm to find the longest simple path in the graph. 51 | Center: design a linear-time algorithm to find a vertex such that its maximum distance from any other vertex is minimized. 52 | */ 53 | 54 | public static void diameter(Graph g) { 55 | assert g.V() > 0; 56 | //first pass, find all paths from 0, and find the farest vertice from 0 57 | int max = farest(g, 0); 58 | //second pass, from the farest vertice, find all paths from it 59 | BreadthFirstPaths path = new BreadthFirstPaths(g, max); 60 | int end = farest(g, max); 61 | for (Integer v : path.pathTo(end)) { 62 | System.out.println(v); 63 | } 64 | } 65 | 66 | private static int farest(Graph g, int v) { 67 | BreadthFirstPaths path = new BreadthFirstPaths(g, v); 68 | int max = 0; 69 | int len = 0; 70 | for (int i = 1; i < g.V(); i++) { 71 | if (path.distTo(i) > len) { 72 | max = i; 73 | len = path.distTo(i); 74 | } 75 | } 76 | return max; 77 | } 78 | 79 | public static int center(Graph g) { 80 | assert g.V() > 0; 81 | //first find the farest, as above 82 | int start = farest(g, 0); 83 | int end = farest(g, start); 84 | BreadthFirstPaths spath = new BreadthFirstPaths(g, start); 85 | BreadthFirstPaths epath = new BreadthFirstPaths(g, end); 86 | int result = start; 87 | for (int i = 0; i < g.V(); i++) { 88 | if (spath.distTo(i) == epath.distTo(i) || spath.distTo(i) == epath.distTo(i) + 1) 89 | result = i; 90 | } 91 | return result; 92 | } 93 | 94 | /* 95 | Question 3 96 | Euler cycle. 97 | An Euler cycle in a graph is a cycle (not necessarily simple) that uses every edge in the graph exactly one. 98 | Show that a connected graph has an Euler cycle if and only if every vertex has even degree. 99 | Design a linear-time algorithm to determine whether a graph has an Euler cycle, and if so, find one. 100 | */ 101 | 102 | /* 103 | use the even edge number to check, then use dfs to print the cycle 104 | */ 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /assignments/burrowswheeler/MoveToFront.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Queue; 4 | import algs4.SymbolDigraph; 5 | import stdlib.*; 6 | 7 | import java.util.ArrayList; 8 | 9 | /** 10 | * Created by Leon on 8/24/15. 11 | */ 12 | public class MoveToFront { 13 | private final static int R = 256; 14 | private static int[] encodings = new int[R]; 15 | private static char[] ranks = new char[R]; 16 | 17 | private static void initEncoding() { 18 | for (int i = 0; i < R; i++) { 19 | encodings[i] = i; 20 | ranks[i] = (char) i; 21 | } 22 | } 23 | 24 | private static void moveToFront(char c) { 25 | int current = encodings[c]; 26 | 27 | for (int i = current; i > 0; i--) { 28 | ranks[i] = ranks[i - 1]; 29 | encodings[ranks[i]] = i; 30 | } 31 | ranks[0] = c; 32 | encodings[c] = 0; 33 | } 34 | // apply move-to-front encoding, reading from standard input and writing to standard output 35 | public static void encode() { 36 | initEncoding(); 37 | 38 | while (!BinaryStdIn.isEmpty()) { 39 | char c = BinaryStdIn.readChar(); 40 | int out = encodings[c]; 41 | BinaryStdOut.write(out); 42 | moveToFront(c); 43 | } 44 | BinaryStdOut.close(); 45 | } 46 | //DEBUG 47 | private static void dump(Queue q) { 48 | int BYTES_PER_LINE = 16; 49 | int i; 50 | for (i = 0; !q.isEmpty(); i++) { 51 | if (i == 0) StdOut.printf(""); 52 | else if (i % BYTES_PER_LINE == 0) StdOut.printf("\n", i); 53 | else StdOut.print(" "); 54 | StdOut.print(Integer.toHexString(q.dequeue())); 55 | } 56 | if (BYTES_PER_LINE != 0) StdOut.println(); 57 | StdOut.println((i * 8) + " bits"); 58 | } 59 | //DEBUG 60 | private static void encode(String file) { 61 | initEncoding(); 62 | BinaryIn bin = new BinaryIn(file); 63 | Queue output = new Queue(); 64 | 65 | while (!bin.isEmpty()) { 66 | char c = bin.readChar(); 67 | int out = encodings[c]; 68 | output.enqueue(out); 69 | moveToFront(c); 70 | } 71 | dump(output); 72 | } 73 | 74 | // apply move-to-front decoding, reading from standard input and writing to standard output 75 | public static void decode() { 76 | initEncoding(); 77 | 78 | while (!BinaryStdIn.isEmpty()) { 79 | int i = BinaryStdIn.readInt(); 80 | char c = ranks[i]; 81 | BinaryStdOut.write(c); 82 | moveToFront(c); 83 | } 84 | BinaryStdOut.close(); 85 | } 86 | //DEBUG 87 | private static void decode(boolean debug) { 88 | if (!debug) return; 89 | else { 90 | initEncoding(); 91 | String[] input = StdIn.readAllStrings(); 92 | 93 | for (String s : input) { 94 | int i = Integer.parseInt(s, 16); 95 | char c = ranks[i]; 96 | System.out.print(Character.toString(c)); 97 | moveToFront(c); 98 | } 99 | } 100 | } 101 | 102 | // if args[0] is '-', apply move-to-front encoding 103 | // if args[0] is '+', apply move-to-front decoding 104 | public static void main(String[] args) { 105 | if (args[0].equals("-")) encode(); 106 | else if (args[0].equals("+")) decode(); 107 | else throw new IllegalArgumentException("Please use - and + to specify encoding or decoding!"); 108 | 109 | //encode("./resources/burrowswheeler/abra.txt"); 110 | //decode(true); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /assignments/seamcarving/SCUtility.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.Picture; 4 | import stdlib.StdRandom; 5 | 6 | import java.awt.*; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * Created by Leon on 8/9/15. 11 | */ 12 | public class SCUtility { 13 | // create random W-by-H array of tiles 14 | public static Picture randomPicture(int W, int H) { 15 | Picture p = new Picture(W, H); 16 | for (int i = 0; i < W; i++) 17 | for (int j = 0; j < H; j++) { 18 | int r = StdRandom.uniform(255); 19 | int g = StdRandom.uniform(255); 20 | int b = StdRandom.uniform(255); 21 | Color c = new Color(r, g, b); 22 | p.set (i, j, c); 23 | } 24 | return p; 25 | } 26 | 27 | 28 | public static double[][] toEnergyMatrix(SeamCarver sc) 29 | { 30 | double[][] returnDouble = new double[sc.width()][sc.height()]; 31 | for (int i = 0; i < sc.width(); i++) 32 | for (int j = 0; j < sc.height(); j++) 33 | returnDouble[i][j] = sc.energy(i, j); 34 | 35 | return returnDouble; 36 | } 37 | 38 | // displays grayvalues as energy (converts to picture, calls show) 39 | public static void showEnergy(SeamCarver sc) 40 | { 41 | doubleToPicture(toEnergyMatrix(sc)).show(); 42 | } 43 | 44 | public static Picture toEnergyPicture(SeamCarver sc) 45 | { 46 | double[][] energyMatrix = toEnergyMatrix(sc); 47 | return doubleToPicture(energyMatrix); 48 | } 49 | 50 | // converts a double matrix of values into a normalized picture 51 | // values are normalized by the maximum grayscale value 52 | public static Picture doubleToPicture(double[][] grayValues) 53 | { 54 | 55 | //each 1D array in the matrix represents a single column, so number 56 | //of 1D arrays is the width, and length of each array is the height 57 | int width = grayValues.length; 58 | int height = grayValues[0].length; 59 | 60 | Picture p = new Picture(width, height); 61 | 62 | double maxVal = 0; 63 | for (int i = 0; i < width; i++) 64 | for (int j = 0; j < height; j++) 65 | if (grayValues[i][j] > maxVal) 66 | maxVal = grayValues[i][j]; 67 | 68 | if (maxVal == 0) 69 | return p; //return black picture 70 | 71 | for (int i = 0; i < width; i++) 72 | for (int j = 0; j < height; j++) 73 | { 74 | float normalizedGrayValue = (float) grayValues[i][j] / (float) maxVal; 75 | p.set(i, j, new Color(normalizedGrayValue, normalizedGrayValue, normalizedGrayValue)); 76 | } 77 | 78 | return p; 79 | } 80 | 81 | 82 | // This method is useful for debugging seams. It overlays red 83 | // pixels over the calculate seam. Due to the lack of a copy 84 | // constructor, it also alters the original picture. 85 | 86 | public static Picture seamOverlay(Picture p, boolean horizontal, int[] seamIndices) 87 | { 88 | Picture overlaid = new Picture(p.width(), p.height()); 89 | 90 | for (int i = 0; i < p.width(); i++) 91 | for (int j = 0; j < p.height(); j++) 92 | overlaid.set(i, j, p.get(i, j)); 93 | 94 | int width = p.width(); 95 | int height = p.height(); 96 | 97 | //if horizontal seam, then set one pixel in every column 98 | if (horizontal) 99 | for (int i = 0; i < width; i++) 100 | overlaid.set(i, seamIndices[i], new Color(255, 0, 0)); 101 | else //if vertical, put one pixel in every row 102 | for (int j= 0; j < height; j++) 103 | overlaid.set(seamIndices[j], j, new Color(255, 0, 0)); 104 | 105 | return overlaid; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /jobinterviewquestions/AnalysisofAlgorithms.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by Leon on 6/30/15. 7 | */ 8 | public class AnalysisofAlgorithms { 9 | /* 10 | Question 1 11 | 3-SUM in quadratic time. Design an algorithm for the 3-SUM problem that takes time proportional to N2 in the worst case. 12 | You may assume that you can sort the N integers in time proportional to N2 or better. 13 | */ 14 | 15 | private boolean sum(int[] a, int key) { 16 | int left = 0; 17 | int right = a.length - 1; 18 | int value = a[key]; 19 | while (left < right) { 20 | if (left == key || a[left] + a[right] < value) left++; 21 | else if (right == key || a[left] + a[right] > value) right--; 22 | else return true; 23 | } 24 | return false; 25 | } 26 | 27 | public boolean threesum(int[] a) { 28 | Arrays.sort(a); 29 | 30 | for (int i = 0; i < a.length; i++) { 31 | if (sum(a, i)) return true; 32 | } 33 | return false; 34 | } 35 | 36 | /* 37 | Question 2 38 | Search in a bitonic array. 39 | An array is bitonic if it is comprised of an increasing sequence of integers followed immediately by a decreasing sequence of integers. 40 | Write a program that, given a bitonic array of N distinct integer values, determines whether a given integer is in the array. 41 | Standard version: Use ∼3lgN compares in the worst case. 42 | Signing bonus: Use ∼2lgN compares in the worst case (and prove that no algorithm can guarantee to perform fewer than ∼2lgN compares in the worst case). 43 | */ 44 | private boolean binsearch(int[] a, int left, int right, int key) { 45 | if (a[left] < a[right]) { 46 | while (left < right) { 47 | int mid = left + (right - left) / 2; 48 | if (a[mid] < key) left = mid + 1; 49 | else if (a[mid] > key) right = mid - 1; 50 | else return true; 51 | } 52 | } 53 | else { 54 | while (left < right) { 55 | int mid = left + (right - left) / 2; 56 | if (a[mid] < key) right = mid - 1; 57 | else if (a[mid] > key) left = mid + 1; 58 | else return true; 59 | } 60 | } 61 | return false; 62 | } 63 | 64 | public boolean serarch(int[] a, int key) { 65 | int left = 0; 66 | int right = a.length - 1; 67 | 68 | while (left < right) { 69 | int mid = left + (right - left) / 2; 70 | if (a[mid] < key) { 71 | if (a[mid] < a[mid + 1]) left = mid + 1; 72 | else right = mid - 1; 73 | } 74 | else if (a[mid] > key) { 75 | if (a[mid] < a[mid + 1]) { 76 | if (binsearch(a, 0, mid - 1, key)) return true; 77 | else left = mid + 1; 78 | } 79 | else { 80 | if (binsearch(a, mid + 1, a.length - 1, key)) return true; 81 | else right = mid - 1; 82 | } 83 | } 84 | else return true; 85 | } 86 | return false; 87 | } 88 | 89 | /* 90 | Egg drop. Suppose that you have an N-story building (with floors 1 through N) and plenty of eggs. 91 | An egg breaks if it is dropped from floor T or higher and does not break otherwise. 92 | Your goal is to devise a strategy to determine the value of T given the following limitations on the number of eggs and tosses: 93 | Version 0: 1 egg, ≤T tosses. 94 | Version 1: ∼1lgN eggs and ∼1lgN tosses. 95 | Version 2: ∼lgT eggs and ∼2lgT tosses. 96 | Version 3: 2 eggs and ∼2N‾‾√ tosses. 97 | Version 4: 2 eggs and ≤cT‾‾√ tosses for some fixed constant c. 98 | */ 99 | 100 | 101 | } 102 | -------------------------------------------------------------------------------- /jobinterviewquestions/ElementarySymbolTables.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.DoublingRatio; 4 | import algs4.Queue; 5 | 6 | /** 7 | * Created by Leon on 7/20/15. 8 | */ 9 | public class ElementarySymbolTables { 10 | /* 11 | Question 1 12 | Java autoboxing and equals(). Consider two double values a and b and their corresponding Double values x and y. 13 | Find values such that (a == b) is true but x.equals(y) is false. 14 | Find values such that (a == b) is false but x.equals(y) is true. 15 | */ 16 | 17 | /* 18 | 1. a=0.0, b=-0.0 19 | 2. a=b=Double.NaN 20 | */ 21 | 22 | 23 | /* 24 | Question 2 25 | Check if a binary tree is a BST. 26 | Given a binary tree where each Node contains a key, determine whether it is a binary search tree. Use extra space proportional to the height of the tree. 27 | */ 28 | 29 | private class Node { 30 | private int key; // sorted by key 31 | private int val; // associated data 32 | private Node left, right; // left and right subtrees 33 | private int N; // number of nodes in subtree 34 | 35 | public Node(int key, int val, int N) { 36 | this.key = key; 37 | this.val = val; 38 | this.N = N; 39 | } 40 | } 41 | 42 | public boolean checkBST(Node p, int min, int max) { 43 | if (p == null) return true; 44 | if(p.key >= max || p.key <= min ) return false; 45 | return checkBST(p.left, min, p.key) && checkBST(p.right, p.key, max); 46 | } 47 | 48 | /* 49 | Question 3 50 | Inorder traversal with constant extra space. 51 | Design an algorithm to perform an inorder traversal of a binary search tree using only a constant amount of extra space. 52 | */ 53 | 54 | public void inorder(Node root) { 55 | if (root == null) return; 56 | 57 | Node previous; 58 | Node current = root; 59 | while (current != null) { 60 | //current has no left child, print current, then go right 61 | if (current.left == null) { 62 | System.out.println(current.val); 63 | current = current.right; 64 | } 65 | else { 66 | previous = current.left; 67 | 68 | //go down to current left children's rightmost child 69 | while (previous.right != null && previous.right != current) { 70 | previous = previous.right; 71 | } 72 | 73 | //if the rightmost child hasn't being linked to current, then link it, and traverse to current left 74 | if (previous.right == null) { 75 | previous.right = current; 76 | current = current.left; 77 | } 78 | //if the rightmost child already linked to current (current left children being traversed), then print current and cut the link to restore tree structure 79 | else { 80 | previous.right = null; 81 | System.out.println(current.val); 82 | current = current.right; 83 | } 84 | } 85 | } 86 | } 87 | 88 | /* 89 | Question 4 90 | Web tracking. Suppose that you are tracking N web sites and M users and you want to support the following API: 91 | User visits a website. 92 | How many times has a given user visited a given site? 93 | What data structure or data structures would you use? 94 | */ 95 | 96 | /* 97 | Symbol table of user as keys, value are symbol table of website as keys and visit numbers as value 98 | */ 99 | 100 | public static void main(String[] args) { 101 | double a = Double.NaN; 102 | double b = Double.NaN; 103 | Double x = new Double(a); 104 | Double y = new Double(b); 105 | System.out.println(a==b); 106 | System.out.println(x.equals(y)); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /jobinterviewquestions/ElementarySorts.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.Shell; 4 | 5 | /** 6 | * Created by Leon on 7/9/15. 7 | */ 8 | public class ElementarySorts { 9 | /* 10 | Question 1 11 | Intersection of two sets. 12 | Given two arrays a[] and b[], each containing N distinct 2D points in the plane, 13 | design a subquadratic algorithm to count the number of points that are contained both in array a[] and array b[]. 14 | */ 15 | 16 | class Point implements Comparable{ 17 | private int x; 18 | private int y; 19 | 20 | public Point(int x, int y) { 21 | this.x = x; 22 | this.y = y; 23 | } 24 | 25 | @Override 26 | public int compareTo(Point that) { 27 | if (that.x > this.x) return -1; 28 | if (that.x < this.x) return 1; 29 | if (that.y > this.y) return -1; 30 | if (that.y < this.y) return 1; 31 | return 0; 32 | } 33 | 34 | public int countIntersection(Point[] a, Point[] b) { 35 | Shell.sort(a); 36 | Shell.sort(b); 37 | 38 | int i = 0; 39 | int j = 0; 40 | int count = 0; 41 | 42 | while (i < a.length && j < b.length) { 43 | if (a[i].compareTo(b[j]) == 0) { 44 | count++; 45 | i++; 46 | j++; 47 | } 48 | else if (a[i].compareTo(b[j]) < 0) i++; 49 | else j++; 50 | } 51 | return count; 52 | } 53 | } 54 | 55 | /* 56 | Question 2 57 | Permutation. 58 | Given two integer arrays of size N, design a subquadratic algorithm to determine whether one is a permutation of the other. 59 | That is, do they contain exactly the same entries but, possibly, in a different order. 60 | */ 61 | 62 | public boolean isPerm(Integer[] a, Integer[] b) { 63 | if (a.length != b.length) return false; 64 | Shell.sort(a); 65 | Shell.sort(b); 66 | 67 | for (int i = 0; i < a.length; i++) { 68 | if (a[i] != b[i]) return false; 69 | } 70 | return true; 71 | } 72 | 73 | /* 74 | Question 3 75 | Dutch national flag. Given an array of N buckets, each containing a red, white, or blue pebble, sort them by color. The allowed operations are: 76 | swap(i,j): swap the pebble in bucket i with the pebble in bucket j. 77 | color(i): color of pebble in bucket i. 78 | The performance requirements are as follows: 79 | At most N calls to color(). 80 | At most N calls to swap(). 81 | Constant extra space. 82 | */ 83 | 84 | enum Pebble { 85 | Red, 86 | White, 87 | Blue 88 | } 89 | 90 | class Buckets { 91 | private Pebble[] pebbles; 92 | 93 | private Pebble color(int i) { 94 | return pebbles[i]; 95 | } 96 | 97 | private int compare(Pebble p) { 98 | Pebble white = Pebble.White; 99 | return p.ordinal() - white.ordinal(); 100 | } 101 | 102 | private void swap(int i, int j) { 103 | Pebble tmp = pebbles[i]; 104 | pebbles[i] = pebbles[j]; 105 | pebbles[j] = tmp; 106 | } 107 | 108 | public void sort() { 109 | assert pebbles.length > 0; 110 | int r = 0; 111 | int runner = 0; 112 | int b = pebbles.length - 1; 113 | 114 | while (runner <= b) { 115 | Pebble color = color(runner); 116 | int cmp = compare(color); 117 | if (cmp < 0) { 118 | swap(runner++, r++); 119 | } 120 | else if (cmp > 0) { 121 | swap(runner, b--); 122 | } 123 | else { 124 | runner++; 125 | } 126 | 127 | } 128 | } 129 | 130 | 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /assignments/8puzzle/Solver.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.MinPQ; 4 | import algs4.Stack; 5 | import algs4.SymbolDigraph; 6 | import stdlib.In; 7 | import stdlib.StdOut; 8 | 9 | /** 10 | * Created by Leon on 7/20/15. 11 | */ 12 | public class Solver { 13 | private class SearchNode implements Comparable{ 14 | private Board board; 15 | private SearchNode previous; 16 | private int moves; 17 | 18 | SearchNode(Board board) { 19 | this.board = board; 20 | this.previous = null; 21 | this.moves = 0; 22 | } 23 | 24 | public int compareTo(SearchNode that) { 25 | if (this.board.manhattan() + this.moves > that.board.manhattan() + that.moves) return 1; 26 | if (this.board.manhattan() + this.moves < that.board.manhattan() + that.moves) return -1; 27 | return 0; 28 | } 29 | } 30 | 31 | private SearchNode solutionNode; 32 | private SearchNode twinsolutionNode; 33 | 34 | public boolean isSolvable() { 35 | return moves() >= 0; 36 | } 37 | 38 | public int moves() { 39 | return solutionNode.moves; 40 | } 41 | 42 | public Iterable solution() { 43 | if (!isSolvable()) return null; 44 | 45 | Stack steps = new Stack(); 46 | 47 | while (solutionNode != null) { 48 | steps.push(solutionNode.board); 49 | solutionNode = solutionNode.previous; 50 | } 51 | 52 | return steps; 53 | } 54 | 55 | public Solver(Board initial) { 56 | if (initial == null) throw new NullPointerException("Please initialize the board!"); 57 | 58 | solutionNode = new SearchNode(initial); 59 | twinsolutionNode = new SearchNode(initial.twin()); 60 | 61 | MinPQ solutionQueue = new MinPQ(); 62 | MinPQ twinsolutionQueue = new MinPQ(); 63 | 64 | solutionQueue.insert(solutionNode); 65 | twinsolutionQueue.insert(twinsolutionNode); 66 | 67 | while (true) { 68 | solutionNode = solutionQueue.delMin(); 69 | twinsolutionNode = twinsolutionQueue.delMin(); 70 | 71 | if (twinsolutionNode.board.isGoal()) { 72 | solutionNode.moves = -1; 73 | solutionNode.previous = null; 74 | return; 75 | } 76 | 77 | if (solutionNode.board.isGoal()){ 78 | return; 79 | } 80 | 81 | addSearchNodes(solutionQueue, solutionNode); 82 | addSearchNodes(twinsolutionQueue, twinsolutionNode); 83 | } 84 | } 85 | 86 | private void addSearchNodes(MinPQ q, SearchNode node) { 87 | assert node.board != null; 88 | 89 | for (Board b: node.board.neighbors()) { 90 | if (!b.equals(node.board)) { 91 | SearchNode candidate = new SearchNode(b); 92 | candidate.previous = node; 93 | candidate.moves = node.moves + 1; 94 | q.insert(candidate); 95 | } 96 | } 97 | } 98 | 99 | public static void main(String[] args) { 100 | 101 | // create initial board from file 102 | In in = new In("./resources/8puzzle/puzzle2x2-unsolvable2.txt"); 103 | int N = in.readInt(); 104 | int[][] blocks = new int[N][N]; 105 | for (int i = 0; i < N; i++) 106 | for (int j = 0; j < N; j++) 107 | blocks[i][j] = in.readInt(); 108 | Board initial = new Board(blocks); 109 | //System.out.println(initial.isGoal()); 110 | 111 | // solve the puzzle 112 | Solver solver = new Solver(initial); 113 | 114 | // print solution to standard output 115 | if (!solver.isSolvable()) 116 | StdOut.println("No solution possible"); 117 | else { 118 | StdOut.println("Minimum number of moves = " + solver.moves()); 119 | for (Board board : solver.solution()) 120 | StdOut.println(board); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /jobinterviewquestions/BalancedSearchTrees.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.Queue; 4 | import algs4.RedBlackBST; 5 | import algs4.ST; 6 | import stdlib.In; 7 | import stdlib.StdIn; 8 | 9 | import java.util.LinkedList; 10 | 11 | /** 12 | * Created by Leon on 7/22/15. 13 | */ 14 | public class BalancedSearchTrees { 15 | /* 16 | Question 1 17 | Red-black BST with no extra memory. 18 | Describe how to save the memory for storing the color information when implementing a red-black BST. 19 | */ 20 | 21 | /* 22 | Question 2 23 | Document search. 24 | Design an algorithm that takes a sequence of N document words and a sequence of M query words 25 | and find the shortest interval in which the M query words appear in the document in the order given. 26 | The length of an interval is the number of words in that interval. 27 | */ 28 | 29 | public static void main(String[] args) { 30 | In in = new In(""); 31 | String[] words = in.readAllStrings(); 32 | 33 | ST> windices = new ST>(); 34 | 35 | for (int i = 0; i < words.length; i++) { 36 | if (!windices.contains(words[i])) { 37 | Queue tmp = new Queue(); 38 | tmp.enqueue(i); 39 | windices.put(words[i], tmp); 40 | } 41 | else { 42 | Queue tmp = windices.get(words[i]); 43 | tmp.enqueue(i); 44 | windices.put(words[i], tmp); 45 | } 46 | } 47 | 48 | int bestlo = -1; 49 | int besthi = words.length; 50 | String[] query = StdIn.readAllStrings(); 51 | Queue[] queues = (Queue[]) new Queue[query.length]; 52 | 53 | for (int i = 0; i < query.length; i++) { 54 | queues[i] = windices.get(query[i]); 55 | } 56 | 57 | Queue starts = windices.get(query[0]); 58 | 59 | for (Integer start: starts) { 60 | boolean end = true; 61 | int lo = start; 62 | int hi = lo; 63 | 64 | for (int i = 1; i < queues.length; i++) { 65 | while (!queues[i].isEmpty() && queues[i].peek() <= hi) queues[i].dequeue(); 66 | if (queues[i].isEmpty()) { 67 | end = false; 68 | break; 69 | } 70 | else { 71 | hi = queues[i].peek(); 72 | } 73 | } 74 | if (end && hi - lo < besthi - bestlo) { 75 | besthi = hi; 76 | bestlo = lo; 77 | } 78 | } 79 | 80 | if (bestlo >= 0) { 81 | int interval = besthi - bestlo; 82 | System.out.println("Shortest interval found: " + interval); 83 | } 84 | else { 85 | System.out.println("Not found"); 86 | } 87 | } 88 | 89 | /* 90 | Question 3 91 | Generalized queue. 92 | Design a generalized queue data type that supports all of the following operations in logarithmic time (or better) in the worst case. 93 | Create an empty data structure. 94 | Append an item to the end of the queue. 95 | Remove an item from the front of the queue. 96 | Return the ith item in the queue. 97 | Remove the ith item from the queue. 98 | */ 99 | 100 | class GeneralizedQueue { 101 | private int index; 102 | private RedBlackBST store; 103 | 104 | GeneralizedQueue() { 105 | index = 0; 106 | store = new RedBlackBST(); 107 | } 108 | 109 | public void append(Item item) { 110 | store.put(index++, item); 111 | } 112 | 113 | public void removeFront() { 114 | store.deleteMin(); 115 | } 116 | 117 | public Item get(int i) { 118 | int key = store.rank(i); 119 | return store.get(key); 120 | } 121 | 122 | public void delete(int i) { 123 | store.delete(store.rank(i)); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /assignments/wordnet/SAP.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.BreadthFirstDirectedPaths; 4 | import algs4.Digraph; 5 | import algs4.Interval1D; 6 | import algs4.SET; 7 | import stdlib.In; 8 | import stdlib.StdIn; 9 | import stdlib.StdOut; 10 | 11 | /** 12 | * Created by Leon on 7/30/15. 13 | */ 14 | public class SAP { 15 | private static final int INFINITY = Integer.MAX_VALUE; 16 | private final Digraph digraph; 17 | // constructor takes a digraph (not necessarily a DAG) 18 | public SAP(Digraph G) { 19 | digraph = G; 20 | } 21 | 22 | // length of shortest ancestral path between v and w; -1 if no such path 23 | public int length(int v, int w) { 24 | validate(v); 25 | validate(w); 26 | 27 | BreadthFirstDirectedPaths vpaths = new BreadthFirstDirectedPaths(digraph, v); 28 | BreadthFirstDirectedPaths wpaths = new BreadthFirstDirectedPaths(digraph, w); 29 | 30 | return sapHelper(vpaths, wpaths, true); 31 | } 32 | 33 | // a common ancestor of v and w that participates in a shortest ancestral path; -1 if no such path 34 | public int ancestor(int v, int w) { 35 | validate(v); 36 | validate(w); 37 | 38 | BreadthFirstDirectedPaths vpaths = new BreadthFirstDirectedPaths(digraph, v); 39 | BreadthFirstDirectedPaths wpaths = new BreadthFirstDirectedPaths(digraph, w); 40 | 41 | return sapHelper(vpaths, wpaths, false); 42 | } 43 | 44 | // length of shortest ancestral path between any vertex in v and any vertex in w; -1 if no such path 45 | public int length(Iterable v, Iterable w) { 46 | if (v == null || w == null) throw new NullPointerException(); 47 | validate(v); 48 | validate(w); 49 | 50 | BreadthFirstDirectedPaths vpaths = new BreadthFirstDirectedPaths(digraph, v); 51 | BreadthFirstDirectedPaths wpaths = new BreadthFirstDirectedPaths(digraph, w); 52 | 53 | return sapHelper(vpaths, wpaths, true); 54 | } 55 | 56 | // a common ancestor that participates in shortest ancestral path; -1 if no such path 57 | public int ancestor(Iterable v, Iterable w) { 58 | if (v == null || w == null) throw new NullPointerException(); 59 | validate(v); 60 | validate(w); 61 | 62 | BreadthFirstDirectedPaths vpaths = new BreadthFirstDirectedPaths(digraph, v); 63 | BreadthFirstDirectedPaths wpaths = new BreadthFirstDirectedPaths(digraph, w); 64 | 65 | return sapHelper(vpaths, wpaths, false); 66 | } 67 | 68 | private void validate(int v) { 69 | if (v < 0 || v > digraph.V() - 1) throw new IndexOutOfBoundsException(); 70 | } 71 | 72 | private void validate(Iterable v) { 73 | for (Integer i : v) { 74 | validate(i); 75 | } 76 | } 77 | 78 | private int sapHelper(BreadthFirstDirectedPaths vpaths, BreadthFirstDirectedPaths wpaths, boolean length) { 79 | int minlen = INFINITY; 80 | int ancestor = -1; 81 | for (int i = 0; i < digraph.V(); i++) { 82 | if (vpaths.hasPathTo(i) && wpaths.hasPathTo(i)) { 83 | int vlen = vpaths.distTo(i); 84 | int wlen = wpaths.distTo(i); 85 | if (vlen + wlen < minlen) { 86 | minlen = vlen + wlen; 87 | ancestor = i; 88 | } 89 | } 90 | } 91 | if (length) return minlen < INFINITY ? minlen : -1; 92 | else return ancestor; 93 | } 94 | 95 | // do unit testing of this class 96 | public static void main(String[] args) { 97 | In in = new In("./resources/sap/digraph1.txt"); 98 | Digraph G = new Digraph(in); 99 | SAP sap = new SAP(G); 100 | //while (!StdIn.isEmpty()) { 101 | SET v = new SET(); 102 | SET w = new SET(); 103 | v.add(7);//v.add(3); 104 | w.add(4);w.add(5); 105 | int length = sap.length(v, w); 106 | int ancestor = sap.ancestor(v, w); 107 | StdOut.printf("length = %d, ancestor = %d\n", length, ancestor); 108 | //} 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /jobinterviewquestions/Mergesort.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import stdlib.StdRandom; 4 | 5 | /** 6 | * Created by Leon on 7/12/15. 7 | */ 8 | public class Mergesort { 9 | /* 10 | Question 1 11 | Merging with smaller auxiliary array. 12 | Suppose that the subarray a[0] to a[N-1] is sorted and the subarray a[N] to a[2*N-1] is sorted. 13 | How can you merge the two subarrays so that a[0] to a[2*N-1] is sorted using an auxiliary array of size N (instead of 2N)? 14 | */ 15 | private boolean less(Comparable a, Comparable b) { 16 | return a.compareTo(b) < 0; 17 | } 18 | 19 | public void mergeWithSmaller(Comparable[] a, Comparable[] aux) { 20 | int N = aux.length; 21 | assert a.length == 2*N; 22 | 23 | for (int i = 0; i < N; i++) { 24 | aux[i] = a[i]; 25 | } 26 | 27 | int l = 0; 28 | int r = N; 29 | 30 | int i = 0; 31 | for (; i < N; i++) { 32 | if (less(aux[l], a[r])) a[i] = aux[l++]; 33 | else a[i] = a[r++]; 34 | } 35 | 36 | while (l < N) { 37 | if (r >= 2*N || less(aux[l], a[r]) ) a[i++] = aux[l++]; 38 | else a[i++] = a[r++]; 39 | } 40 | } 41 | 42 | /* 43 | Question 2 44 | Counting inversions. 45 | An inversion in an array a[] is a pair of entries a[i] and a[j] such that ia[j]. 46 | Given an array, design a linearithmic algorithm to count the number of inversions. 47 | */ 48 | 49 | private int merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) { 50 | for (int k = lo; k <= hi; k++) { 51 | aux[k] = a[k]; 52 | } 53 | 54 | int k = lo; 55 | int i = lo; 56 | int j = mid + 1; 57 | int count = 0; 58 | 59 | while (k < hi) { 60 | if (i > mid) a[k++] = aux[j++]; 61 | else if (j > hi) a[k++] = aux[i++]; 62 | else if (less(aux[j], aux[i])) { 63 | count += mid + 1 - i; 64 | a[k++] = aux[j++]; 65 | } 66 | else a[k++] = aux[i++]; 67 | } 68 | return count; 69 | } 70 | 71 | public int countInversion(Comparable[] a) { 72 | Comparable[] aux = new Comparable[a.length]; 73 | int count = 0; 74 | 75 | for (int sz = 1; sz < a.length; sz += sz) { 76 | for (int i = 0; i < a.length - sz; i += 2*sz) { 77 | int lo = i; 78 | int m = i + sz - 1; 79 | int hi = Math.min(i + 2*sz - 1, a.length - 1); 80 | count += merge(a, aux, lo, m, hi); 81 | } 82 | } 83 | return count; 84 | } 85 | 86 | 87 | /* 88 | Question 3 89 | Shuffling a linked list. 90 | Given a singly-linked list containing N items, rearrange the items uniformly at random. 91 | Your algorithm should consume a logarithmic (or constant) amount of extra memory and run in time proportional to NlogN in the worst case. 92 | */ 93 | 94 | private class Node { 95 | Object item; 96 | Node next; 97 | } 98 | 99 | private void merge(Node lh, Node rh) { 100 | Node left = lh; 101 | Node right = rh; 102 | 103 | if (StdRandom.uniform(1) > 0) { 104 | lh = right; 105 | right = right.next; 106 | } 107 | else { 108 | left = left.next; 109 | } 110 | 111 | Node runner = lh; 112 | 113 | while (right != null || left != null) { 114 | if (left == null) { 115 | runner.next = right; 116 | right =right.next; 117 | } 118 | else if (right == null) { 119 | runner.next = left; 120 | left = left.next; 121 | } 122 | else if (StdRandom.uniform(1) > 0) { 123 | runner.next = right; 124 | right = right.next; 125 | } 126 | else { 127 | runner.next = left; 128 | left = left.next; 129 | } 130 | runner = runner.next; 131 | } 132 | } 133 | 134 | public void shuffle(Node head, int N) { 135 | if (N == 1) return; 136 | 137 | int k = 1; 138 | Node mid = head; 139 | while (k < N / 2) { 140 | mid = mid.next; 141 | k++; 142 | } 143 | Node rh = mid.next; 144 | mid.next = null; 145 | shuffle(head, N / 2); 146 | shuffle(rh, N - N / 2); 147 | merge(head, rh); 148 | } 149 | 150 | 151 | } 152 | -------------------------------------------------------------------------------- /jobinterviewquestions/DirectedGraph.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.*; 4 | 5 | import java.util.Iterator; 6 | 7 | /** 8 | * Created by Leon on 7/29/15. 9 | */ 10 | public class DirectedGraph { 11 | /* 12 | Question 1 13 | Shortest directed cycle. 14 | Given a digraph G, 15 | design an efficient algorithm to find a directed cycle with the minimum number of edges (or report that the graph is acyclic). 16 | The running time of your algorithm should be at most proportional to V(E+V) and use space proportional to E+V, 17 | where V is the number of vertices and E is the number of edges. 18 | */ 19 | 20 | private boolean[] marked; 21 | private boolean[] onStack; 22 | private int[] edgeTo; 23 | Stack cycle; 24 | private int[] group; 25 | 26 | private void dfs(Digraph g, int v) { 27 | marked[v] = true; 28 | onStack[v] = true; 29 | 30 | for (int i : g.adj(v)) { 31 | if (!marked[i]) { 32 | edgeTo[i] = v; 33 | dfs(g, i); 34 | } 35 | else if (onStack[i]) { 36 | cycle = new Stack(); 37 | for (int x = v; x != i; x = edgeTo[x]) 38 | cycle.push(x); 39 | cycle.push(i); 40 | cycle.push(v); 41 | } 42 | } 43 | onStack[v] = false; 44 | } 45 | 46 | public DirectedGraph(Digraph g) { 47 | marked = new boolean[g.V()]; 48 | onStack = new boolean[g.V()]; 49 | edgeTo = new int[g.V()]; 50 | 51 | for (int v = 0; v < g.V(); v++) { 52 | if (!marked[v]) dfs(g, v); 53 | } 54 | } 55 | 56 | public Iterable cycle() { 57 | return cycle; 58 | } 59 | 60 | public boolean hasCycle() { 61 | return cycle != null; 62 | } 63 | 64 | 65 | /* 66 | Question 2 67 | Hamiltonian path in a DAG. 68 | Given a directed acyclic graph, 69 | design a linear-time algorithm to determine whether it has a Hamiltonian path (a simple path that visits every vertex), and if so, find one. 70 | */ 71 | 72 | public Iterable hamiltonianPath(Digraph g) { 73 | //assert g is DAG 74 | Digraph gr = g.reverse(); 75 | int v = findEnd(gr, 0); 76 | if (v > 0) { 77 | int count = 1; 78 | Queue path = new Queue(); 79 | while (g.outdegree(v) == 1) { 80 | path.enqueue(v); 81 | for (int i : g.adj(v)) v = i; 82 | count++; 83 | } 84 | if (count == g.V()) return path; 85 | } 86 | return null; 87 | } 88 | 89 | private int findEnd(Digraph g, int v) { 90 | if (g.outdegree(v) == 0) return v; 91 | if (g.outdegree(v) == 1) { 92 | for (int i : g.adj(v)) return findEnd(g, i); 93 | } 94 | return -1; 95 | } 96 | 97 | /* 98 | Question 3 99 | Reachable vertex. 100 | DAG: Design a linear-time algorithm to determine whether a DAG has a vertex that is reachable from every other vertex, and if so, find one. 101 | Digraph: Design a linear-time algorithm to determine whether a digraph has a vertex that is reachable from every other vertex, and if so, find one. 102 | */ 103 | 104 | public int findVinDAG(Digraph g) { 105 | //assert g is DAG 106 | Digraph gr = g.reverse(); 107 | for (int v = 0; v < gr.V(); v++) { 108 | if (g.outdegree(v) == 0) { 109 | int count = 1; 110 | boolean[] marked = new boolean[gr.V()]; 111 | marked[v] = true; 112 | Queue visited = new Queue(); 113 | visited.enqueue(v); 114 | while (!visited.isEmpty()) { 115 | int w = visited.dequeue(); 116 | for (int i : gr.adj(w)) { 117 | if (!marked[i]) { 118 | marked[i] = true; 119 | count++; 120 | visited.enqueue(i); 121 | } 122 | } 123 | } 124 | if (count == g.V()) return v; 125 | break; 126 | } 127 | } 128 | return -1; 129 | } 130 | 131 | private int[] id; 132 | private int count; 133 | 134 | private void dfs_kernel(Digraph g, int v) { 135 | marked[v] = true; 136 | id[v] = count; 137 | for (int w : g.adj(v)) { 138 | if (!marked[w]) dfs_kernel(g, w); 139 | } 140 | } 141 | 142 | public int findV(Digraph g) { 143 | TarjanSCC scc = new TarjanSCC(g); 144 | int c = scc.count(); 145 | 146 | Digraph kDAG = new Digraph(c); 147 | 148 | DepthFirstOrder dfs = new DepthFirstOrder(g.reverse()); 149 | marked = new boolean[g.V()]; 150 | id = new int[g.V()]; 151 | for (int v : dfs.reversePost()) { 152 | if (!marked[v]) { 153 | dfs_kernel(g, v); 154 | count++; 155 | } 156 | } 157 | 158 | for (int v : dfs.reversePost()) { 159 | for (int w : g.adj(v)) { 160 | if (id[w] != id[v]) kDAG.addEdge(id[v], id[w]); 161 | } 162 | } 163 | 164 | return findVinDAG(kDAG); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /jobinterviewquestions/PriorityQueue.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.MaxPQ; 4 | import algs4.MinPQ; 5 | import algs4.Queue; 6 | import algs4.SymbolDigraph; 7 | 8 | /** 9 | * Created by Leon on 7/19/15. 10 | */ 11 | public class PriorityQueue { 12 | /* 13 | Question 1 14 | Dynamic median. 15 | Design a data type that supports insert in logarithmic time, find-the-median in constant time, and remove-the-median in logarithmic time. 16 | */ 17 | 18 | class MediaHeap { 19 | private MaxPQ left; 20 | private MinPQ right; 21 | private int L; 22 | private int R; 23 | 24 | MediaHeap() { 25 | left = new MaxPQ(); 26 | right = new MinPQ(); 27 | } 28 | 29 | public double findMedian() { 30 | int L = left.size(); 31 | int R = right.size(); 32 | if (L == R) 33 | return ((double)left.max() + (double)right.min()) / 2; 34 | else if (L > R) 35 | return left.max(); 36 | else 37 | return right.min(); 38 | } 39 | 40 | public void insert(int key) { 41 | double median = findMedian(); 42 | int L = left.size(); 43 | int R = right.size(); 44 | if (key <= median) { 45 | left.insert(key); 46 | if (L - R > 1) 47 | right.insert(left.delMax()); 48 | } 49 | else { 50 | right.insert(key); 51 | if (R - L > 1) 52 | left.insert(right.delMin()); 53 | } 54 | } 55 | 56 | public void removeMedian() { 57 | int L = left.size(); 58 | int R = right.size(); 59 | if (L > R) { 60 | left.delMax(); 61 | } 62 | else { 63 | right.delMin(); 64 | } 65 | } 66 | 67 | } 68 | 69 | /* 70 | Question 2 71 | Randomized priority queue. 72 | Describe how to add the methods sample() and delRandom() to our binary heap implementation. 73 | The two methods return a key that is chosen uniformly at random among the remaining keys, with the latter method also removing that key. 74 | The sample() method should take constant time; the delRandom() method should take logarithmic time. 75 | Do not worry about resizing the underlying array. 76 | */ 77 | 78 | /* 79 | generate random number from 0 - N, sample() just return that number 80 | when delete random, exchange with last, delete last, then compare with parent and children to decide whether swim or sink 81 | */ 82 | 83 | /* 84 | Question 3 85 | Taxicab numbers. 86 | A taxicab number is an integer that can be expressed as the sum of two cubes of integers in two different ways: a^3+b^3=c^3+d^3. 87 | For example, 1729=9^3+10^3=1^3+12^3. Design an algorithm to find all taxicab numbers with a, b, c, and d less than N. 88 | Version 1: Use time proportional to N^2logN and space proportional to N^2. 89 | Version 2: Use time proportional to N^2logN and space proportional to N. 90 | */ 91 | 92 | class Taxicab implements Comparable{ 93 | int n1; 94 | int n2; 95 | int cube; 96 | 97 | Taxicab(int n1, int n2) { 98 | this.n1 = n1; 99 | this.n2 = n2; 100 | this.cube = n1 * n1 * n1 + n2 * n2 * n2; 101 | } 102 | 103 | @Override 104 | public int compareTo(Taxicab that) { 105 | if (that.cube > this.cube) return -1; 106 | if (that.cube < this.cube) return 1; 107 | return 0; 108 | } 109 | 110 | @Override 111 | public boolean equals(Object o) { 112 | if (o instanceof Taxicab) { 113 | if (((Taxicab)o).compareTo(this) == 0) 114 | return true; 115 | } 116 | return false; 117 | } 118 | 119 | @Override 120 | public String toString() { 121 | return "number: " + cube + " (" + n1 + ", " + n2 + ")"; 122 | } 123 | } 124 | 125 | public void findTaxinumber(int N) { 126 | MinPQ candidates = new MinPQ(); 127 | 128 | for (int i = 1; i <= N; i++) { 129 | for (int j = i + 1; j <= N; j++) { 130 | Taxicab t = new Taxicab(i, j); 131 | if (candidates.size() < N) { 132 | candidates.insert(t); 133 | } 134 | else { 135 | Queue temp = new Queue(); 136 | Taxicab min = candidates.delMin(); 137 | while (candidates.min().equals(min)) { 138 | temp.enqueue(candidates.delMin()); 139 | } 140 | if (!t.equals(min)) { 141 | candidates.insert(t); 142 | } 143 | else { 144 | temp.enqueue(t); 145 | } 146 | if (!temp.isEmpty()) { 147 | for (Taxicab taxi: temp) { 148 | System.out.println(taxi); 149 | } 150 | System.out.println(min); 151 | } 152 | } 153 | } 154 | } 155 | } 156 | 157 | public static void main(String[] args) { 158 | PriorityQueue p = new PriorityQueue(); 159 | p.findTaxinumber(12); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /jobinterviewquestions/QuickSort.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.Bag; 4 | import stdlib.In; 5 | 6 | import java.util.TreeMap; 7 | import java.util.TreeSet; 8 | 9 | /** 10 | * Created by Leon on 7/14/15. 11 | */ 12 | public class QuickSort { 13 | /* 14 | Question 1 15 | Nuts and bolts. 16 | A disorganized carpenter has a mixed pile of N nuts and N bolts. 17 | The goal is to find the corresponding pairs of nuts and bolts. 18 | Each nut fits exactly one bolt and each bolt fits exactly one nut. 19 | By fitting a nut and a bolt together, the carpenter can see which one is bigger 20 | (but the carpenter cannot compare two nuts or two bolts directly). 21 | Design an algorithm for the problem that uses NlogN compares (probabilistically). 22 | */ 23 | 24 | /* 25 | Binary search, compare each nut with bolts already compared (logN! = NlogN time), identify the interval, then divide the bolts in the interval (Sum of N/x = NlogN time) 26 | */ 27 | 28 | class Nut { 29 | private int size; 30 | public int compare(Bolt bolt) { 31 | if (bolt.size > this.size) return -1; 32 | else if (bolt.size < this.size) return 1; 33 | else return 0; 34 | } 35 | } 36 | 37 | class Bolt { 38 | private int size; 39 | } 40 | 41 | public void pair(Bolt[] bolts, Nut[] nuts) { 42 | int n = nuts.length; 43 | assert bolts.length == n; 44 | Nut[] auxN = new Nut[n]; 45 | Bolt[] auxB = new Bolt[n]; //need TreeMap to implement 46 | for (int i = 0; i < n; i++) { 47 | int lo = floor(auxB, nuts[i]); //use floor api in TreeMap 48 | int hi = ceil(auxB, nuts[i]); //use ceil api in TreeMap 49 | int index = partition(bolts, nuts[i], lo, hi); 50 | auxB[index] = bolts[index]; 51 | auxN[index] = nuts[i]; 52 | } 53 | 54 | for (int i = 0; i < n; i++) { 55 | nuts[i] = auxN[i]; 56 | } 57 | } 58 | 59 | private int partition(Bolt[] bolts, Nut nut, int lo, int hi) { 60 | int l = lo; 61 | int r = hi; 62 | while (true) { 63 | while (nut.compare(bolts[++l]) > 0) if (l == hi) break; 64 | while (nut.compare(bolts[--r]) < 0) if (r == lo) break; 65 | if (l >= r) break; 66 | exch(bolts, l, r); 67 | } 68 | return l; 69 | } 70 | 71 | private void exch(Bolt[] bolts, int l, int r) { 72 | Bolt tmp = bolts[l]; 73 | bolts[l] = bolts[r]; 74 | bolts[r] = tmp; 75 | } 76 | 77 | private int floor(Bolt[] b, Nut nut) { 78 | return 0; 79 | } 80 | 81 | private int ceil(Bolt[] b, Nut nut) { 82 | return 0; 83 | } 84 | 85 | 86 | /* 87 | Question 2 88 | Selection in two sorted arrays. 89 | Given two sorted arrays a[] and b[], of sizes N1 and N2, respectively, 90 | design an algorithm to find the kth largest key. 91 | The order of growth of the worst case running time of your algorithm should be logN, where N=N1+N2. 92 | Version 1: N1=N2 and k=N/2 93 | Version 2: k=N/2 94 | Version 3: no restrictions 95 | */ 96 | int MAX = Integer.MAX_VALUE; 97 | int MIN = Integer.MIN_VALUE; 98 | 99 | public int select(int[] a, int ah, int[] b, int bh, int k) { 100 | int n1 = a.length - ah; 101 | int n2 = b.length - bh; 102 | int i = ah + (int)(double)(n1/(n1 + n2)*(k - 1)); 103 | int j = bh + k - i - 1; 104 | int ai = i == n1 ? MAX : a[i]; 105 | int bj = j == n2 ? MAX : b[j]; 106 | int ai1 = i == 0 ? MIN : a[i - 1]; 107 | int bj1 = j == 0 ? MIN : b[j - 1]; 108 | 109 | if (ai > bj1 && ai < bj) return ai; 110 | else if (bj > ai1 && bj < ai) return bj; 111 | else if (ai < bj1) return select(a, i + 1, b, bh, k - i - 1); 112 | else return select(a, ah, b, j + 1, k - j - 1); 113 | } 114 | 115 | /* 116 | Question 3 117 | Decimal dominants. 118 | Given an array with N keys, design an algorithm to find all values that occur more than N/10 times. 119 | The expected running time of your algorithm should be linear. 120 | */ 121 | 122 | class DecimalDominants { 123 | private TreeMap counts; 124 | private int K; 125 | private int N; 126 | private int[] A; 127 | 128 | public DecimalDominants(int[] a, int k) { 129 | A = a; 130 | N = a.length; 131 | K = k; 132 | 133 | buildCounts(a); 134 | } 135 | 136 | private void buildCounts(int[] a) { 137 | for (int i = 0; i < N; i++) { 138 | if (counts.containsKey(i)) counts.put(i, counts.get(i) + 1); 139 | else counts.put(i, 1); 140 | if (counts.keySet().size() >= K) removeCounts(); 141 | } 142 | } 143 | 144 | private void removeCounts() { 145 | for (int k : counts.keySet()) { 146 | int c = counts.get(k); 147 | if (c > 1) counts.put(k, c - 1); 148 | else counts.remove(k); 149 | } 150 | } 151 | 152 | public Iterable find() { 153 | Bag result = new Bag(); 154 | for (int k : counts.keySet()) { 155 | if (count(k) > N/K) result.add(k); 156 | } 157 | return result; 158 | } 159 | 160 | private int count(int k) { 161 | int count = 0; 162 | for (int i = 0; i < N; i++) { 163 | if (A[i] == k) count++; 164 | } 165 | return count; 166 | } 167 | } 168 | 169 | 170 | } 171 | -------------------------------------------------------------------------------- /assignments/wordnet/WordNet.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.*; 4 | import stdlib.In; 5 | import stdlib.StdIn; 6 | 7 | import java.util.HashMap; 8 | 9 | /** 10 | * Created by Leon on 7/30/15. 11 | */ 12 | public class WordNet { 13 | private final HashMap> idmap; 14 | private final HashMap> wordmap; 15 | private final Digraph G; 16 | private final SAP sap; 17 | private int V; 18 | 19 | // constructor takes the name of the two input files 20 | public WordNet(String synsets, String hypernyms){ 21 | idmap = new HashMap>(); 22 | wordmap = new HashMap>(); 23 | readSynsets(synsets); 24 | 25 | G = new Digraph(V); 26 | readHypernyms(hypernyms); 27 | sap = new SAP(G); 28 | 29 | checkCycle(); 30 | checkRoot(); 31 | 32 | 33 | } 34 | 35 | // returns all WordNet nouns 36 | public Iterable nouns(){ 37 | return wordmap.keySet(); 38 | } 39 | 40 | // is the word a WordNet noun? 41 | public boolean isNoun(String word){ 42 | return wordmap.containsKey(word); 43 | } 44 | 45 | // distance between nounA and nounB (defined below) 46 | public int distance(String nounA, String nounB){ 47 | if (!isNoun(nounA) || !isNoun(nounB)) throw new IllegalArgumentException(); 48 | Iterable A = wordmap.get(nounA); 49 | Iterable B = wordmap.get(nounB); 50 | 51 | return sap.length(A, B); 52 | } 53 | 54 | // a synset (second field of synsets.txt) that is the common ancestor of nounA and nounB 55 | // in a shortest ancestral path (defined below) 56 | public String sap(String nounA, String nounB){ 57 | if (!isNoun(nounA) || !isNoun(nounB)) throw new IllegalArgumentException(); 58 | Iterable A = wordmap.get(nounA); 59 | Iterable B = wordmap.get(nounB); 60 | 61 | int ancestor = sap.ancestor(A, B); 62 | Bag result = idmap.get(ancestor); 63 | return concat(result); 64 | } 65 | //helper function for read in file for synsets 66 | private void readSynsets(String synsets) { 67 | In SynsetsIn = new In(synsets); 68 | V = 0; 69 | 70 | while (SynsetsIn.hasNextLine()) { 71 | String line = SynsetsIn.readLine(); 72 | String[] tokens = line.split(","); 73 | Integer id = Integer.parseInt(tokens[0]); 74 | String[] nouns = tokens[1].split(" "); 75 | Bag words = new Bag(); 76 | 77 | for (int i = 0; i < nouns.length; i++) { 78 | words.add(nouns[i]); 79 | Bag ids = new Bag(); 80 | if (this.wordmap.containsKey(nouns[i])) 81 | ids = this.wordmap.get(nouns[i]); 82 | ids.add(id); 83 | this.wordmap.put(nouns[i], ids); 84 | } 85 | 86 | idmap.put(id, words); 87 | 88 | if (id > this.V) this.V = id; 89 | } 90 | this.V = this.V + 1; 91 | } 92 | //helper function for read in file for hypernyms 93 | private void readHypernyms(String hypernyms) { 94 | In HypernymsIn = new In(hypernyms); 95 | 96 | while (HypernymsIn.hasNextLine()) { 97 | String line = HypernymsIn.readLine(); 98 | String[] token = line.split(","); 99 | int v = Integer.parseInt(token[0]); 100 | for (int i = 1; i < token.length; i++) { 101 | int w = Integer.parseInt(token[i]); 102 | this.G.addEdge(v, w); 103 | } 104 | } 105 | } 106 | //helper function for checking whether digraph has cycle 107 | private void checkCycle() { 108 | DirectedCycle cycle = new DirectedCycle(this.G); 109 | if (cycle.hasCycle()) throw new IllegalArgumentException("Digraph has cycle!"); 110 | } 111 | //helper function for checking whether digraph is rooted 112 | private void checkRoot() { 113 | Digraph Gr = this.G.reverse(); 114 | for (int v = 0; v < V; v++) { 115 | if (this.G.outdegree(v) == 0) { 116 | int count = 1; 117 | boolean[] marked = new boolean[V]; 118 | marked[v] = true; 119 | Queue visited = new Queue(); 120 | visited.enqueue(v); 121 | while (!visited.isEmpty()) { 122 | int w = visited.dequeue(); 123 | for (int i : Gr.adj(w)) { 124 | if (!marked[i]) { 125 | marked[i] = true; 126 | count++; 127 | visited.enqueue(i); 128 | } 129 | } 130 | } 131 | if (count != V) throw new IllegalArgumentException("Digraph not rooted!"); 132 | } 133 | } 134 | } 135 | //heloer function for concat nouns 136 | private String concat(Bag nouns) { 137 | String result = ""; 138 | for (String noun : nouns) { 139 | result = result + noun; 140 | } 141 | return result; 142 | } 143 | 144 | // do unit testing of this class 145 | public static void main(String[] args){ 146 | //In SynsetsIn = new In("./resources/wordnet/synsets15.txt"); 147 | //In HypernymsIn = new In("./resources/wordnet/hypernyms6TwoAncestors.txt"); 148 | 149 | WordNet wordNet = new WordNet("./resources/wordnet/synsets8.txt", "./resources/wordnet/hypernyms8ManyAncestors.txt"); 150 | System.out.println(wordNet.distance("a", "c")); 151 | System.out.println(wordNet.sap("a", "c")); 152 | 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /assignments/8puzzle/Board.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Queue; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * Created by Leon on 7/20/15. 9 | */ 10 | public class Board { 11 | private int dim; 12 | private int[][] blocks; 13 | 14 | public Board(int[][] blocks) { 15 | this.blocks = copyMDArray(blocks); 16 | dim = blocks.length; 17 | } 18 | 19 | public int dimension() { 20 | return dim; 21 | } 22 | 23 | public int hamming() { 24 | int hamming = 0; 25 | for (int i = 0; i < dim; i++) { 26 | for (int j = 0; j < dim; j++) { 27 | if (blocks[i][j] != i*dim + j + 1) hamming++; 28 | } 29 | } 30 | return hamming - 1; 31 | } 32 | 33 | public int manhattan() { 34 | int manhattan = 0; 35 | for (int i = 0; i < dim; i++) { 36 | for (int j = 0; j < dim; j++) { 37 | if (blocks[i][j] > 0) { 38 | int row = (blocks[i][j] - 1) / dim; 39 | int col = (blocks[i][j] - 1) % dim; 40 | manhattan += Math.abs(row - i) + Math.abs(col - j); 41 | } 42 | } 43 | } 44 | return manhattan; 45 | } 46 | 47 | public boolean isGoal() { 48 | return hamming() == 0; 49 | } 50 | 51 | public Board twin() { 52 | // a board obtained by exchanging two adjacent blocks in the same row 53 | 54 | int[][] blocksCopy = copyMDArray(blocks); 55 | if (blocksCopy.length <= 1) { 56 | return new Board(blocksCopy); 57 | } 58 | 59 | int row = 0; 60 | int col = 0; 61 | int value = 0; 62 | int lastValue = blocksCopy[0][0]; 63 | 64 | for (row = 0; row < blocksCopy.length; row++) { 65 | for (col = 0; col < blocksCopy.length; col++) { 66 | value = blocksCopy[row][col]; 67 | if (value != 0 && lastValue != 0 && col > 0) { 68 | blocksCopy[row][col] = lastValue; 69 | blocksCopy[row][col - 1] = value; 70 | return new Board(blocksCopy); 71 | } 72 | lastValue = value; 73 | } 74 | } 75 | 76 | return null; 77 | } 78 | 79 | public boolean equals(Object obj) { 80 | if (this == obj) 81 | return true; 82 | if (obj == null) 83 | return false; 84 | if (!(obj instanceof Board)) 85 | return false; 86 | Board other = (Board) obj; 87 | if (!Arrays.deepEquals(this.blocks, other.blocks)) 88 | return false; 89 | return true; 90 | } 91 | 92 | public Iterable neighbors() { 93 | 94 | // neighbors are all boards that can be reached in ONE move 95 | // this means 96 | 97 | // use queue -- FIFO, and add boards to it in order 98 | Queue queue = new Queue(); 99 | 100 | int[][] zero = findEmpty(); 101 | int row = zero[0][0]; 102 | int col = zero[0][1]; 103 | 104 | // if NOT the top row, swap with one above 105 | if (row > 0) { 106 | int[][] blocksCopy = copyMDArray(blocks); 107 | swap(blocksCopy, row, col, row - 1, col); 108 | queue.enqueue(new Board(blocksCopy)); 109 | } 110 | 111 | // if NOT the bottom row, swap with one below 112 | if (row < blocks.length - 1) { 113 | int[][] blocksCopy = copyMDArray(blocks); 114 | swap(blocksCopy, row, col, row + 1, col); 115 | queue.enqueue(new Board(blocksCopy)); 116 | } 117 | 118 | // if NOT the far left col, swap with left 119 | if (col > 0) { 120 | int[][] blocksCopy = copyMDArray(blocks); 121 | swap(blocksCopy, row, col, row, col - 1); 122 | queue.enqueue(new Board(blocksCopy)); 123 | } 124 | 125 | // if NOT the far right col, swap with right 126 | if (col < blocks.length - 1) { 127 | int[][] blocksCopy = copyMDArray(blocks); 128 | swap(blocksCopy, row, col, row, col + 1); 129 | queue.enqueue(new Board(blocksCopy)); 130 | } 131 | 132 | return queue; 133 | } 134 | 135 | public String toString() { 136 | StringBuilder sb = new StringBuilder(); 137 | sb.append(blocks.length + "\n"); 138 | sb.append(toString2D(blocks)); 139 | return sb.toString(); 140 | } 141 | 142 | private static int[][] copyMDArray(int[][] input) { 143 | int[][] output = new int[input.length][input[0].length]; 144 | for (int i = 0; i < input.length; i++) { 145 | output[i] = Arrays.copyOf(input[i], input[i].length); 146 | } 147 | return output; 148 | } 149 | 150 | private int[][] findEmpty() { 151 | for (int i = 0; i < blocks.length; i++) { 152 | for (int j = 0; j < blocks.length; j++) { 153 | if (blocks[i][j] == 0) { 154 | return new int[][] { { i, j } }; 155 | } 156 | } 157 | } 158 | return null; 159 | } 160 | 161 | private static void swap(int[][] input, int row, int col, int toRow, int toCol) { 162 | int first = input[row][col]; 163 | int second = input[toRow][toCol]; 164 | input[row][col] = second; 165 | input[toRow][toCol] = first; 166 | } 167 | 168 | // need this util because System.arrayCopy and Arrays.copyOf 169 | // will get this wrong and use same pointers 170 | // (a 2D array is a 1D array of 1D arrays, etc) 171 | private static String toString2D(int[][] input) { 172 | StringBuilder sb = new StringBuilder(); 173 | for (int i = 0; i < input.length; i++) { 174 | for (int j = 0; j < input.length; j++) { 175 | int digit = input[i][j]; 176 | sb.append(" " + digit + " "); 177 | } 178 | if (i < input.length - 1) { 179 | sb.append("\n"); 180 | } 181 | } 182 | return sb.toString(); 183 | } 184 | 185 | 186 | 187 | 188 | } 189 | -------------------------------------------------------------------------------- /jobinterviewquestions/SubstringSearch.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | 4 | import algs4.Queue; 5 | 6 | /** 7 | * Created by Leon on 8/18/15. 8 | */ 9 | public class SubstringSearch { 10 | /* 11 | Question 1 12 | Cyclic rotation of a string. 13 | A string s is a cyclic rotation of a string t 14 | if s and t have the same length and s consists of a suffix of t followed by a prefix of t. 15 | For example, "winterbreak" is a cyclic rotation of "breakwinter" (and vice versa). 16 | Design a linear-time algorithm to determine whether one string is a cyclic rotation of another. 17 | */ 18 | 19 | public static boolean isCyclicRotation(String s1, String s2) { 20 | String concat = s1 + s1; 21 | //use knuth-morris-pratt to create a pattern dfa of s2 22 | KMP pattern = new KMP(s2); 23 | return pattern.search(concat) < concat.length(); 24 | } 25 | 26 | static class KMP { 27 | private int[][] dfa; 28 | private int R; 29 | private String pattern; 30 | 31 | KMP(String pattern) { 32 | this.R = 256; 33 | this.pattern = pattern; 34 | 35 | int M = pattern.length(); 36 | dfa = new int[R][M]; 37 | dfa[pattern.charAt(0)][0] = 1; 38 | 39 | for (int X = 0, j = 1; j < M; j++) { 40 | for (int c = 0; c < R; c++) { 41 | dfa[c][j] = dfa[c][X]; 42 | } 43 | dfa[pattern.charAt(j)][j] = j + 1; 44 | X = dfa[pattern.charAt(j)][X]; 45 | } 46 | } 47 | 48 | int search(String txt) { 49 | int M = pattern.length(); 50 | int N = txt.length(); 51 | int i, j; 52 | for (i = 0, j = 0; i < N && j < M; i++) { 53 | j = dfa[txt.charAt(i)][j]; 54 | } 55 | if (j == M) return i - M; 56 | return N; 57 | } 58 | 59 | String tendemRepeat(String s) { 60 | int M = pattern.length(); 61 | int N = s.length(); 62 | 63 | Queue positions = new Queue(); 64 | 65 | for (int i = 0, j = 0; i < N; i++) { 66 | j = dfa[s.charAt(i)][j]; 67 | if (j == M) { 68 | positions.enqueue(i - M + 1); 69 | j = 0; 70 | } 71 | } 72 | if (positions.isEmpty()) throw new IllegalArgumentException("Input does not contain the base pattern!"); 73 | int max = 1; 74 | int seq = 1; 75 | int end = 0; 76 | int previous = positions.dequeue(); 77 | while (!positions.isEmpty()) { 78 | int current = positions.dequeue(); 79 | if (current == previous + M) { 80 | seq++; 81 | } 82 | else { 83 | if (seq > max) { 84 | max = seq; 85 | end = previous + M; 86 | seq = 1; 87 | } 88 | } 89 | previous = current; 90 | } 91 | 92 | if (seq > max) { 93 | end = previous + M; 94 | max = seq; 95 | } 96 | if (max == 1) return "Input does not have a tendem repeat!"; 97 | else return s.substring(end - M*max, end); 98 | } 99 | } 100 | 101 | /* 102 | Question 2 103 | Tandem repeat. 104 | A tandem repeat of a base string b within a string s 105 | is a substring of s consisting of at least one consecutive copy of the base string b. 106 | Given b and s, design an algorithm to find a tandem repeat of b within s of maximum length. 107 | Your algorithm should run in time proportional to M+N, where M is length of b and N is the length s. 108 | 109 | For example, 110 | if s is "abcabcababcaba" and b is "abcab", then "abcababcab" is the tandem substring of maximum length (2 copies). 111 | */ 112 | 113 | /* 114 | see KMP.tendemRepeat 115 | */ 116 | 117 | /* 118 | Question 3 119 | Longest palindromic substring. 120 | Given a string s, find the longest substring that is a palindrome in expected linearithmic time. 121 | Signing bonus: Do it in linear time in the worst case. 122 | */ 123 | 124 | /* 125 | for linearithmic algorithm, use karp-rabin to hash substring and reverse substring to find palindrome, then use binary search to find the largest number of substring length 126 | */ 127 | 128 | /* 129 | linear time algorithm, from leetcode 130 | */ 131 | 132 | //preprocess string, to avoid dealing with odd and even number problem 133 | private static String preprocess(String s) { 134 | if (s.length() == 0) return "^$"; 135 | String result = "^";// insert ^ at start 136 | for (int i = 0; i < s.length(); i++) { 137 | result = result + "#" + s.substring(i, i + 1); 138 | } 139 | result += "#$"; // insert $ at end 140 | return result; 141 | } 142 | 143 | public static String longestPalindromeSubstring(String s) { 144 | String t = preprocess(s); 145 | int[] p = new int[t.length()]; 146 | int center = 0; 147 | int right = 0; //the right boundary of previous center 148 | //first run, create index array p, p[i] is the length / 2 of palindrome that use i as center 149 | for (int i = 1; i < t.length() - 1; i++) { 150 | int i_mirror = 2*center - i; //mirror position of current position 151 | p[i] = (right > i) ? Math.min(right - i, p[i_mirror]) : 0; //initialize p[i] with its mirror position data or boundary limit 152 | while (t.charAt(i + 1 + p[i]) == t.charAt(i - 1 - p[i])) p[i]++; //try to expand i as center 153 | if (i + p[i] > right) { //if expand exceed the old right boundary, make i the new center, move right boundary 154 | center = i; 155 | right = i + p[i]; 156 | } 157 | } 158 | 159 | //second run, find the largest p[i], and return substring 160 | int maxlen = 0; 161 | int centerindex = 0; 162 | for (int i = 1; i < p.length - 1; i++) { 163 | if (p[i] > maxlen) { 164 | maxlen = p[i]; 165 | centerindex = i; 166 | } 167 | } 168 | 169 | return s.substring((centerindex - 1 - maxlen) / 2, (centerindex - 1 + maxlen) / 2); 170 | } 171 | 172 | public static void main(String[] args) { 173 | KMP kmp = new KMP("abc"); 174 | System.out.print(kmp.tendemRepeat("abcd")); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /jobinterviewquestions/StackandQueues.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.Stack; 4 | 5 | import java.util.NoSuchElementException; 6 | 7 | /** 8 | * Created by Leon on 7/5/15. 9 | */ 10 | public class StackandQueues { 11 | /* 12 | Question 1 13 | Queue with two stacks. 14 | Implement a queue with two stacks so that each queue operations takes a constant amortized number of stack operations. 15 | */ 16 | 17 | class TwoStackQueue { 18 | private Stack s1; 19 | private Stack s2; 20 | 21 | public TwoStackQueue() { 22 | s1 = new Stack(); 23 | s2 = new Stack(); 24 | } 25 | 26 | public boolean isEmpty() { 27 | return s1.isEmpty() && s2.isEmpty(); 28 | } 29 | 30 | public int size() { 31 | return s1.size() + s2.size(); 32 | } 33 | 34 | private void transfer() { 35 | while (!s1.isEmpty()) { 36 | Item tmp = s1.pop(); 37 | s2.push(tmp); 38 | } 39 | } 40 | 41 | public Item peek() { 42 | if (isEmpty()) throw new NoSuchElementException("algs4.Queue underflow"); 43 | if (s2.isEmpty()) transfer(); 44 | return s2.peek(); 45 | } 46 | 47 | public void enqueue(Item item) { 48 | s1.push(item); 49 | } 50 | 51 | public Item dequeue() { 52 | if (isEmpty()) throw new NoSuchElementException("algs4.Queue underflow"); 53 | if (s2.isEmpty()) transfer(); 54 | return s2.pop(); 55 | } 56 | } 57 | 58 | /* 59 | Question 2 60 | Stack with max. 61 | Create a data structure that efficiently supports the stack operations (push and pop) and also a return-the-maximum operation. 62 | Assume the elements are reals numbers so that you can compare them. 63 | */ 64 | 65 | class MaxStack { 66 | private int N; 67 | private Node first; 68 | private Node max; 69 | 70 | private class Node { 71 | private double item; 72 | private Node next; 73 | } 74 | 75 | public MaxStack() { 76 | N = 0; 77 | first = null; 78 | max = null; 79 | } 80 | 81 | public double getMax() { 82 | return max.item; 83 | } 84 | 85 | public void push(double item) { 86 | Node oldfirst = first; 87 | first = new Node(); 88 | first.item = item; 89 | first.next = oldfirst; 90 | N++; 91 | if (item >= getMax()) { 92 | Node oldmax = max; 93 | max = new Node(); 94 | max.next = oldmax; 95 | } 96 | } 97 | 98 | public double pop() { 99 | double tmp = first.item; 100 | first = first.next; 101 | N--; 102 | if (tmp == getMax()) { 103 | max = max.next; 104 | } 105 | return tmp; 106 | } 107 | } 108 | 109 | /* 110 | Question 3 111 | Java generics. Explain why Java prohibits generic array creation. 112 | */ 113 | 114 | /* 115 | Question 4 116 | Detect cycle in a linked list. 117 | A singly-linked data structure is a data structure made up of nodes where each node has a pointer to the next node (or a pointer to null). 118 | Suppose that you have a pointer to the first node of a singly-linked list data structure: 119 | 1. Determine whether a singly-linked data structure contains a cycle. 120 | You may use only two pointers into the list (and no other variables). 121 | The running time of your algorithm should be linear in the number of nodes in the data structure. 122 | 2. If a singly-linked data structure contains a cycle, determine the first node that participates in the cycle. 123 | you may use only a constant number of pointers into the list (and no other variables). 124 | The running time of your algorithm should be linear in the number of nodes in the data structure. 125 | You may not modify the structure of the linked list. 126 | */ 127 | 128 | class CycleLinkedList { 129 | private Node first; 130 | private int size; 131 | 132 | public class Node { 133 | private Item item; 134 | private Node next; 135 | } 136 | 137 | public boolean isCycle() { 138 | Node p1 = first; 139 | Node p2 = first; 140 | 141 | while (p1 != null && p2 != null) { 142 | p1 = p1.next; 143 | p2 = p2.next.next; 144 | if (p1 == p2) break; 145 | } 146 | if (p1 == null) return false; 147 | else return true; 148 | } 149 | 150 | public Node getStart() { 151 | Node p1 = first; 152 | Node p2 = first; 153 | int count = 0; 154 | while (count < size) { 155 | p2 = p1.next; 156 | p1 = p1.next.next; 157 | count += 2; 158 | } 159 | if (size % 2 == 0) return p1; 160 | else return p2; 161 | } 162 | } 163 | 164 | /* 165 | Question 5 166 | Clone a linked structure with two pointers per node. 167 | Suppose that you are given a reference to the first node of a linked structure where each node has two pointers: 168 | one pointer to the next node in the sequence (as in a standard singly-linked list) and one pointer to an arbitrary node. 169 | 170 | Design a linear-time algorithm to create a copy of the doubly-linked structure. 171 | You may modify the original linked structure, but you must end up with two copies of the original. 172 | */ 173 | 174 | private class Node { 175 | private String item; 176 | private Node next; 177 | private Node random; 178 | } 179 | 180 | public Node copyRandomLinkedList(Node head) { 181 | if (head == null) return null; 182 | //first pass, add copy nodes in between singly-linked list 183 | Node p = head; 184 | while (p != null) { 185 | Node copy = new Node(); 186 | copy.item = p.item; 187 | copy.next = p.next; 188 | p.next = copy; 189 | p = p.next.next; 190 | } 191 | //second pass, add random pointers for copy nodes 192 | p = head; 193 | while (p != null) { 194 | if (p.random != null) p.next.random = p.random.next; 195 | p = p.next.next; 196 | } 197 | 198 | //final pass, break the links between copy and original list 199 | p = head; 200 | Node newhead = p.next; 201 | while (p != null) { 202 | Node copy = p.next; 203 | p.next = copy.next; 204 | if (p.next != null) copy.next = p.next.next; 205 | p = p.next; 206 | } 207 | return newhead; 208 | } 209 | 210 | public static void main(String[] args) { 211 | Node n = null; 212 | //Node m = n.next; 213 | } 214 | 215 | 216 | } 217 | -------------------------------------------------------------------------------- /jobinterviewquestions/RadixSorts.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by Leon on 8/12/15. 7 | */ 8 | public class RadixSorts { 9 | /* 10 | Question 1 11 | 2-sum. 12 | Given an array a of N 64-bit integers and a target value T, 13 | determine whether there are two distinct integers i and j such that ai+aj=T. 14 | Your algorithm should run in linear time in the worst case. 15 | */ 16 | 17 | /* 18 | radix sort the array, then two pointers run 19 | */ 20 | //radix sort for 64 bit int, from algs4 21 | private static void sort(int[] a) { 22 | int BITS = 64; 23 | int W = BITS / 8; 24 | int R = 1 << 8; 25 | int MASK = R - 1; 26 | 27 | int N = a.length; 28 | int[] aux = new int[N]; 29 | 30 | for (int d = 0; d < W; d++) { 31 | int[] count = new int[R+1]; 32 | // compute freq 33 | for (int i = 0; i < N; i++) { 34 | int c = (a[i] >> 8*d) & MASK; 35 | count[c + 1]++; 36 | } 37 | 38 | // compute cumulates 39 | for (int r = 0; r < R; r++) 40 | count[r+1] += count[r]; 41 | 42 | // for most significant byte, 0x80-0xFF comes before 0x00-0x7F 43 | if (d == W-1) { 44 | int shift1 = count[R] - count[R/2]; 45 | int shift2 = count[R/2]; 46 | for (int r = 0; r < R/2; r++) 47 | count[r] += shift1; 48 | for (int r = R/2; r < R; r++) 49 | count[r] -= shift2; 50 | } 51 | 52 | // move data 53 | for (int i = 0; i < N; i++) { 54 | int c = (a[i] >> 8*d) & MASK; 55 | aux[count[c]++] = a[i]; 56 | } 57 | 58 | // copy back 59 | for (int i = 0; i < N; i++) 60 | a[i] = aux[i]; 61 | } 62 | } 63 | 64 | public boolean twoSum(int[] a, int T) { 65 | assert a.length > 1; 66 | sort(a); 67 | 68 | int l = 0; 69 | int r = a.length - 1; 70 | 71 | while (l < r) { 72 | if (a[l] + a[r] < T) l++; 73 | else if (a[l] + a[r] > T) r--; 74 | else return true; 75 | } 76 | return false; 77 | } 78 | 79 | /* 80 | Question 2 81 | American flag sort. 82 | Given an array with N distinct values between 0 and R−1, 83 | rearrange them in ascending order in linear time and with extra space at most proportional to R. 84 | */ 85 | 86 | public static void sortR(int[] a, int R) { 87 | int n = a.length; 88 | 89 | int[] count = new int[R]; 90 | for (int i = 0; i < n; i++) { 91 | count[a[i]]++; 92 | } 93 | int k = 0; 94 | int r = 0; 95 | while (k < n) { 96 | while (count[r]-- > 0) a[k++] = r; 97 | r++; 98 | } 99 | } 100 | 101 | /* 102 | Question 3 103 | Cyclic rotations. 104 | Two strings s and t are cyclic rotations of one another if they have the same length and s consists of a suffix of t followed by a prefix of t. 105 | For example, "suffixsort" and "sortsuffix" are cyclic rotations. 106 | 107 | Given N distinct strings, 108 | each of length L, 109 | design an algorithm to determine whether there exists a pair of distinct strings that are cyclic rotations of one another. 110 | For example, the following list of N=12 strings of length L=10 contains exactly one pair of strings ("suffixsort" and "sortsuffix") 111 | that are cyclic rotations of one another. 112 | 113 | algorithms polynomial sortsuffix boyermoore 114 | structures minimumcut suffixsort stackstack 115 | binaryheap digraphdfs stringsort digraphbfs 116 | The order of growth of the running time should be NL2 (or better) in the worst case. Assume that the alphabet size R is a small constant. 117 | 118 | Signing bonus. Do it in NL time in the worst case. 119 | */ 120 | //substring function make this function n^2 121 | private static String[] suffixes(String s) { 122 | int n = s.length(); 123 | String[] suffiexs = new String[n]; 124 | 125 | for (int i = 0; i < n; i++) { 126 | suffiexs[i] = s.substring(i) + s.substring(0, i); 127 | } 128 | return suffiexs; 129 | } 130 | //explicitly sort the strings 131 | private static void sort(String[] a, int W) { 132 | int N = a.length; 133 | int R = 256; // extend ASCII alphabet size 134 | String[] aux = new String[N]; 135 | 136 | for (int d = W-1; d >= 0; d--) { 137 | // sort by key-indexed counting on dth character 138 | 139 | // compute frequency counts 140 | int[] count = new int[R+1]; 141 | for (int i = 0; i < N; i++) 142 | count[a[i].charAt(d) + 1]++; 143 | 144 | // compute cumulates 145 | for (int r = 0; r < R; r++) 146 | count[r+1] += count[r]; 147 | 148 | // move data 149 | for (int i = 0; i < N; i++) 150 | aux[count[a[i].charAt(d)]++] = a[i]; 151 | 152 | // copy back 153 | for (int i = 0; i < N; i++) 154 | a[i] = aux[i]; 155 | } 156 | } 157 | //implicitly sort the circular suffixes, keep the sort order in a index array 158 | private static void sortSuffixes(String s, int[] indices) { 159 | int N = s.length(); 160 | int R = 256; 161 | int[] aux = new int[N]; 162 | 163 | for (int d = N - 1; d >= 0; d--) { 164 | int[] count = new int[R+1]; 165 | 166 | for (int i = 0; i < N; i++) { 167 | count[s.charAt((d + indices[i]) % N) + 1]++; 168 | } 169 | 170 | for (int r = 0; r < R; r++) { 171 | count[r + 1] += count[r]; 172 | } 173 | 174 | for (int i = 0; i < N; i++) { 175 | aux[count[s.charAt((d + indices[i]) % N)]++] = indices[i]; 176 | } 177 | 178 | for (int i = 0; i < N; i++) 179 | indices[i] = aux[i]; 180 | } 181 | } 182 | 183 | private static int[] initializeIndex(int n) { 184 | int[] result = new int[n]; 185 | for (int i = 0; i < n; i++) { 186 | result[i] = i; 187 | } 188 | return result; 189 | } 190 | 191 | public static boolean pairCyclic(String[] a) { 192 | int n = a.length; 193 | 194 | String[] fingerprint = new String[n]; 195 | 196 | for (int i = 0; i < n; i++) { 197 | int[] indices = initializeIndex(a[i].length()); 198 | sortSuffixes(a[i], indices); 199 | String fp = a[i].substring(indices[0]) + a[i].substring(0, indices[0]); 200 | fingerprint[i] = fp; 201 | } 202 | 203 | sort(fingerprint, n); 204 | 205 | for (int i = 0; i < n - 1; i++) { 206 | if (fingerprint[i] == fingerprint[i + 1]) return true; 207 | } 208 | return false; 209 | } 210 | 211 | public static void main(String[] args) { 212 | int[] a = {1,3,4,4,4,5,6,7,8,3,2,1,3,5,7,89,2,32,0}; 213 | sortR(a, 90); 214 | System.out.println(Arrays.toString(a)); 215 | } 216 | 217 | 218 | } 219 | -------------------------------------------------------------------------------- /assignments/kdtrees/KdTree.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Point2D; 4 | import algs4.Queue; 5 | import org.omg.CORBA.PUBLIC_MEMBER; 6 | import stdlib.StdDraw; 7 | import stdlib.StdIn; 8 | import stdlib.StdOut; 9 | 10 | import java.util.Comparator; 11 | 12 | /** 13 | * Created by Leon on 7/22/15. 14 | */ 15 | public class KdTree { 16 | private static class Node { 17 | private Point2D p; 18 | private RectHV rect; 19 | private Node lb; 20 | private Node rt; 21 | 22 | public Node(Point2D p) { 23 | this.p = p; 24 | } 25 | } 26 | 27 | private Node root; 28 | private int N = 0; 29 | 30 | public boolean isEmpty() { 31 | return N == 0; 32 | } 33 | 34 | public int size() { 35 | return N; 36 | } 37 | 38 | public void insert(Point2D p) { 39 | if (p == null) throw new NullPointerException(); 40 | root = insert(root, p, 0, new RectHV(0, 0, 1, 1)); 41 | N++; 42 | } 43 | 44 | private Node insert(Node node, Point2D p, int level, RectHV rect) { 45 | if (node == null) { 46 | Node n = new Node(p); 47 | n.rect = rect; 48 | return n; 49 | } 50 | int cmp = compare(node, p, level); 51 | if (cmp < 0) { 52 | RectHV lb = divide(rect, node.p, level, -1); 53 | node.lb = insert(node.lb, p, level + 1, lb); 54 | } 55 | else if (cmp > 0) { 56 | RectHV rt = divide(rect, node.p, level, 1); 57 | node.rt = insert(node.rt, p, level + 1, rt); 58 | } 59 | return node; 60 | } 61 | 62 | private RectHV divide(RectHV rect, Point2D p, int level, int orient) { 63 | if (level % 2 == 0) { 64 | double xmin = orient > 0 ? p.x() : rect.xmin(); 65 | double xmax = orient > 0 ? rect.xmax() : p.x(); 66 | return new RectHV(xmin, rect.ymin(), xmax, rect.ymax()); 67 | } 68 | else { 69 | double ymin = orient > 0 ? p.y() : rect.ymin(); 70 | double ymax = orient > 0 ? rect.ymax() : p.y(); 71 | return new RectHV(rect.xmin(), ymin, rect.xmax(), ymax); 72 | } 73 | } 74 | 75 | private int compare(Node node, Point2D p, int level) { 76 | Comparator cmp; 77 | if (level % 2 == 0) cmp = Point2D.X_ORDER; 78 | else cmp = Point2D.Y_ORDER; 79 | return cmp.compare(p, node.p); 80 | } 81 | 82 | public boolean contains(Point2D p) { 83 | if (p == null) throw new NullPointerException(); 84 | return contains(root, p, 0); 85 | } 86 | 87 | private boolean contains(Node node, Point2D p, int level) { 88 | if (node == null) return false; 89 | int cmp = compare(node, p , level); 90 | if (cmp < 0) return contains(node.lb, p, level + 1); 91 | else if (cmp > 0) return contains(node.rt, p, level + 1); 92 | else return true; 93 | } 94 | 95 | public void draw() { 96 | if (isEmpty()) return; 97 | //StdDraw.square(0.5, 0.5, 0.5); 98 | draw(root, 0, new Point2D(0, 1), -1); 99 | } 100 | 101 | private void draw(Node node, int level, Point2D previous, double orient) { 102 | if (node == null) return; 103 | StdDraw.setPenRadius(0.01); 104 | node.p.draw(); 105 | //node.rect.draw(); 106 | drawLine(node, level); 107 | draw(node.lb, level + 1, node.p, -1); 108 | draw(node.rt, level + 1, node.p, 1); 109 | } 110 | 111 | private void drawLine(Node node, int level) { 112 | StdDraw.setPenRadius(0.002); 113 | if (level % 2 == 0) { 114 | StdDraw.setPenColor(StdDraw.RED); 115 | StdDraw.line(node.p.x(), node.rect.ymin(), node.p.x(), node.rect.ymax()); 116 | } 117 | else { 118 | StdDraw.setPenColor(StdDraw.BLUE); 119 | StdDraw.line(node.rect.xmin(), node.p.y(), node.rect.xmax(), node.p.y()); 120 | } 121 | } 122 | 123 | public Iterable range(RectHV rect) { 124 | if (rect == null) throw new NullPointerException(); 125 | if (isEmpty()) return null; 126 | 127 | Queue q = new Queue(); 128 | 129 | findPoints(root, rect, q); 130 | if (q.isEmpty()) return null; 131 | return q; 132 | } 133 | 134 | private void findPoints(Node node, RectHV rect, Queue q){ 135 | if (rect.contains(node.p)) q.enqueue(node.p); 136 | if (node.lb != null && rect.intersects(node.lb.rect)) findPoints(node.lb, rect, q); 137 | if (node.rt != null && rect.intersects(node.rt.rect)) findPoints(node.rt, rect, q); 138 | } 139 | 140 | public Point2D nearest(Point2D p) { 141 | if (p == null) throw new NullPointerException(); 142 | if (isEmpty()) return null; 143 | Point2D nearest = nearest(root, p, new Point2D(100, 100)); 144 | return nearest; 145 | } 146 | 147 | private Point2D nearest(Node node, Point2D p, Point2D nearest) { 148 | double d = p.distanceSquaredTo(nearest); 149 | if (p.distanceSquaredTo(node.p) < d) { 150 | nearest = node.p; 151 | print(nearest); 152 | } 153 | if (node.lb != null && node.lb.rect.distanceSquaredTo(p) < d) { 154 | nearest = nearest(node.lb, p, nearest); 155 | //print(nearest); 156 | d = p.distanceSquaredTo(nearest); 157 | if (node.rt != null && node.rt.rect.distanceSquaredTo(p) < d) { 158 | nearest = nearest(node.rt, p, nearest); 159 | //print(nearest); 160 | } 161 | } 162 | if (node.rt != null && node.rt.rect.distanceSquaredTo(p) < d) { 163 | nearest = nearest(node.rt, p, nearest); 164 | //print(nearest); 165 | d = p.distanceSquaredTo(nearest); 166 | if (node.lb != null && node.lb.rect.distanceSquaredTo(p) < d) { 167 | nearest = nearest(node.lb, p, nearest); 168 | //print(nearest); 169 | } 170 | } 171 | return nearest; 172 | } 173 | 174 | private void print(Point2D p) { 175 | System.out.println(p); 176 | } 177 | 178 | 179 | public static void main(String[] args) { 180 | //KdTree t = new KdTree(); 181 | //double[] input = StdIn.readAllDoubles(); 182 | //for (int i = 0; i < input.length; i+=2) { 183 | // t.insert(new Point2D(input[i], input[i + 1])); 184 | //} 185 | //t.draw(); 186 | //System.out.println(t.contains(new Point2D(input[4], input[5]))); 187 | 188 | RectHV rect = new RectHV(0.0, 0.0, 1.0, 1.0); 189 | StdDraw.show(0); 190 | KdTree kdtree = new KdTree(); 191 | while (true) { 192 | if (StdDraw.mousePressed()) { 193 | double x = StdDraw.mouseX(); 194 | double y = StdDraw.mouseY(); 195 | System.out.printf("%8.6f %8.6f\n", x, y); 196 | Point2D p = new Point2D(x, y); 197 | if (rect.contains(p)) { 198 | StdOut.printf("%8.6f %8.6f\n", x, y); 199 | kdtree.insert(p); 200 | StdDraw.clear(); 201 | kdtree.draw(); 202 | } 203 | } 204 | StdDraw.show(50); 205 | } 206 | 207 | } 208 | } 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /assignments/seamcarving/SeamCarver.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.Picture; 4 | 5 | import java.awt.*; 6 | import java.awt.geom.Arc2D; 7 | 8 | /** 9 | * Created by Leon on 8/6/15. 10 | */ 11 | public class SeamCarver { 12 | private Picture picture; 13 | private int width; 14 | private int height; 15 | private int[][] rgb; 16 | private double[][] energy; 17 | 18 | private double[] seamDist; 19 | private int[] seamPath; 20 | 21 | // create a seam carver object based on the given picture 22 | public SeamCarver(Picture picture) { 23 | this.picture = picture; 24 | width = picture.width(); 25 | height = picture.height(); 26 | 27 | setRGB(picture); 28 | initEnergy(); 29 | 30 | } 31 | 32 | private void initEnergy() { 33 | energy = new double[height][width]; 34 | for (int i = 0; i < height; i++) { 35 | for (int j = 0; j < width; j++) { 36 | setEnergy(i, j); 37 | } 38 | } 39 | } 40 | 41 | private void setRGB(Picture picture) { 42 | rgb = new int[height][width]; 43 | for (int i = 0; i < height; i++) { 44 | for (int j = 0; j < width; j++) { 45 | rgb[i][j] = picture.get(j, i).getRGB(); 46 | } 47 | } 48 | } 49 | 50 | private void setEnergy(int i, int j) { 51 | if (i == 0 || j == 0 || i == height - 1 || j == width - 1) 52 | energy[i][j] = 1000000; 53 | else 54 | energy[i][j] = deltaX(j, i) + deltaY(j, i); 55 | } 56 | 57 | 58 | // current picture 59 | public Picture picture() { 60 | Picture p = new Picture(width, height); 61 | for (int i = 0; i < height; i++) { 62 | for (int j = 0; j < width; j++) { 63 | p.set(j, i, new Color(rgb[i][j])); 64 | } 65 | } 66 | picture = p; 67 | setRGB(picture); 68 | initEnergy(); 69 | return picture; 70 | } 71 | // width of current picture 72 | public int width() { 73 | return width; 74 | } 75 | // height of current picture 76 | public int height() { 77 | return height; 78 | } 79 | // energy of pixel at column x and row y 80 | public double energy(int x, int y) { 81 | return energy[y][x]; 82 | } 83 | //rgb number of col x, row y 84 | private int getRed(int x, int y) { 85 | return (rgb[y][x] >> 16) & 0xFF; 86 | } 87 | 88 | private int getGreen(int x, int y) { 89 | return (rgb[y][x] >> 8) & 0xFF; 90 | } 91 | 92 | private int getBlue(int x, int y) { 93 | return (rgb[y][x] >> 0) & 0xFF; 94 | } 95 | //delta value of col x, row y 96 | private double deltaX(int x, int y) { 97 | int reddiff = getRed(x + 1, y) - getRed(x - 1, y); 98 | int greendiff = getGreen(x + 1, y) - getGreen(x - 1, y); 99 | int bluediff = getBlue(x + 1, y) - getBlue(x - 1, y); 100 | return reddiff*reddiff + greendiff*greendiff + bluediff*bluediff; 101 | } 102 | 103 | private double deltaY(int x, int y) { 104 | int reddiff = getRed(x, y + 1) - getRed(x, y - 1); 105 | int greendiff = getGreen(x, y + 1) - getGreen(x, y - 1); 106 | int bluediff = getBlue(x, y + 1) - getBlue(x, y - 1); 107 | return reddiff*reddiff + greendiff*greendiff + bluediff*bluediff; 108 | } 109 | 110 | // sequence of indices for horizontal seam 111 | public int[] findHorizontalSeam() { 112 | findSP(height, width, false); 113 | int[] result = new int[width]; 114 | for (int v = seamPath[width*height + 1]; v > 0; v = seamPath[v]) 115 | result[(v - 1) / height] = (v - 1) % height; 116 | return result; 117 | } 118 | // sequence of indices for vertical seam 119 | public int[] findVerticalSeam() { 120 | findSP(width, height, true); 121 | int[] result = new int[height]; 122 | for (int v = seamPath[width*height + 1]; v > 0; v = seamPath[v]) 123 | result[(v - 1) / width] = (v - 1) % width; 124 | return result; 125 | } 126 | 127 | private void findSP(int width, int height, boolean vertical) { 128 | int n = width*height; 129 | seamDist = new double[n + 2]; 130 | seamPath = new int[n + 2]; 131 | 132 | for (int i = 1; i < n + 2; i++) { 133 | if (i <= width) seamDist[i] = 0; 134 | else seamDist[i] = Double.POSITIVE_INFINITY; 135 | } 136 | seamDist[0] = 0; 137 | 138 | for (int i = width + 1; i < n + 1; i++) { 139 | relax(i, width, vertical); 140 | } 141 | 142 | for (int i = n - width + 1; i < n + 1; i++) { 143 | relax(n + 1, i, 1000000); 144 | } 145 | } 146 | 147 | private void relax(int i, int width, boolean vertical) { 148 | if (vertical) relaxV(i, width); 149 | else relaxH(i, width); 150 | } 151 | 152 | private void relaxV(int i, int width) { 153 | int x = (i - 1) % width; 154 | int y = (i - 1) / width; 155 | 156 | if (x > 0) relax(i, i - width - 1, energy(x - 1, y - 1)); 157 | if (x < width - 1) relax(i, i - width + 1, energy(x + 1, y - 1)); 158 | relax(i, i - width, energy(x, y - 1)); 159 | } 160 | 161 | private void relaxH(int i, int width) { 162 | int x = (i - 1) / width; 163 | int y = (i - 1) % width; 164 | 165 | if (y % width > 0) relax(i, i - width - 1, energy(x - 1, y - 1)); 166 | if (y % width < width - 1) relax(i, i - width + 1, energy(x - 1, y + 1)); 167 | relax(i, i - width, energy(x - 1, y)); 168 | } 169 | 170 | private void relax(int to, int from, double e) { 171 | if (seamDist[to] > seamDist[from] + e) { 172 | seamDist[to] = seamDist[from] + e; 173 | seamPath[to] = from; 174 | } 175 | } 176 | 177 | // remove horizontal seam from current picture 178 | public void removeHorizontalSeam(int[] seam) { 179 | height--; 180 | for (int i = 0; i < width; i++) { 181 | int rm = seam[i]; 182 | int j = 0; 183 | while (j < height) { 184 | if (j >= rm) { 185 | rgb[j][i] = rgb[j + 1][i]; 186 | energy[j][i] = energy[j + 1][i]; 187 | } 188 | j++; 189 | } 190 | } 191 | 192 | for (int i = 0; i < width; i++) { 193 | int rm = seam[i]; 194 | setEnergy(rm, i); 195 | if (i > 0) setEnergy(rm, i - 1); 196 | if (i < width - 1) setEnergy(rm, i + 1); 197 | if (rm > 0) setEnergy(rm - 1, i); 198 | if (rm < height - 1) setEnergy(rm + 1, i); 199 | } 200 | } 201 | 202 | 203 | 204 | // remove vertical seam from current picture 205 | public void removeVerticalSeam(int[] seam) { 206 | width--; 207 | for (int i = 0; i < height; i++) { 208 | int rm = seam[i]; 209 | int j = 0; 210 | while (j < width) { 211 | if (j >= rm) { 212 | rgb[i][j] = rgb[i][j + 1]; 213 | energy[i][j] = energy[i][j + 1]; 214 | } 215 | 216 | j++; 217 | } 218 | } 219 | 220 | for (int i = 0; i < height; i++) { 221 | int rm = seam[i]; 222 | setEnergy(i, rm); 223 | if (i > 0) setEnergy(i - 1, rm); 224 | if (i < width - 1) setEnergy(i + 1, rm); 225 | if (rm > 0) setEnergy(i, rm - 1); 226 | if (rm < height - 1) setEnergy(i, rm + 1); 227 | } 228 | } 229 | 230 | public static void printEnergy(SeamCarver sc) { 231 | System.out.printf("Printing energy calculated for each pixel.\n"); 232 | 233 | for (int j = 0; j < sc.height(); j++) 234 | { 235 | for (int i = 0; i < sc.width(); i++) 236 | System.out.printf("%9.0f ", sc.energy(i, j)); 237 | 238 | System.out.println(); 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /assignments/Boggle/BoggleBoard.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import stdlib.In; 4 | import stdlib.StdOut; 5 | import stdlib.StdRandom; 6 | 7 | /** 8 | * Created by Leon on 8/19/15. 9 | */ 10 | public class BoggleBoard { 11 | // the 16 Boggle dice (1992 version) 12 | private static final String[] BOGGLE_1992 = { 13 | "LRYTTE", "VTHRWE", "EGHWNE", "SEOTIS", 14 | "ANAEEG", "IDSYTT", "OATTOW", "MTOICU", 15 | "AFPKFS", "XLDERI", "HCPOAS", "ENSIEU", 16 | "YLDEVR", "ZNRNHL", "NMIQHU", "OBBAOJ" 17 | }; 18 | 19 | // the 16 Boggle dice (1983 version) 20 | private static final String[] BOGGLE_1983 = { 21 | "AACIOT", "ABILTY", "ABJMOQ", "ACDEMP", 22 | "ACELRS", "ADENVZ", "AHMORS", "BIFORX", 23 | "DENOSW", "DKNOTU", "EEFHIY", "EGINTV", 24 | "EGKLUY", "EHINPS", "ELPSTU", "GILRUW", 25 | }; 26 | 27 | // the 25 Boggle Master / Boggle Deluxe dice 28 | private static final String[] BOGGLE_MASTER = { 29 | "AAAFRS", "AAEEEE", "AAFIRS", "ADENNN", "AEEEEM", 30 | "AEEGMU", "AEGMNN", "AFIRSY", "BJKQXZ", "CCNSTW", 31 | "CEIILT", "CEILPT", "CEIPST", "DDLNOR", "DHHLOR", 32 | "DHHNOT", "DHLNOR", "EIIITT", "EMOTTT", "ENSSSU", 33 | "FIPRSY", "GORRVW", "HIPRRY", "NOOTUW", "OOOTTU" 34 | }; 35 | 36 | // the 25 Big Boggle dice 37 | private static final String[] BOGGLE_BIG = { 38 | "AAAFRS", "AAEEEE", "AAFIRS", "ADENNN", "AEEEEM", 39 | "AEEGMU", "AEGMNN", "AFIRSY", "BJKQXZ", "CCENST", 40 | "CEIILT", "CEILPT", "CEIPST", "DDHNOT", "DHHLOR", 41 | "DHLNOR", "DHLNOR", "EIIITT", "EMOTTT", "ENSSSU", 42 | "FIPRSY", "GORRVW", "IPRRRY", "NOOTUW", "OOOTTU" 43 | }; 44 | 45 | 46 | // letters and frequencies of letters in the English alphabet 47 | private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 48 | private static final double[] FREQUENCIES = { 49 | 0.08167, 0.01492, 0.02782, 0.04253, 0.12703, 0.02228, 50 | 0.02015, 0.06094, 0.06966, 0.00153, 0.00772, 0.04025, 51 | 0.02406, 0.06749, 0.07507, 0.01929, 0.00095, 0.05987, 52 | 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.00150, 53 | 0.01974, 0.00074 54 | }; 55 | 56 | private final int M; // number of rows 57 | private final int N; // number of columns 58 | private char[][] board; // the M-by-N array of characters 59 | 60 | /** 61 | * Initializes a random 4-by-4 board, by rolling the Hasbro dice. 62 | */ 63 | public BoggleBoard() { 64 | M = 4; 65 | N = 4; 66 | StdRandom.shuffle(BOGGLE_1992); 67 | board = new char[M][N]; 68 | for (int i = 0; i < M; i++) { 69 | for (int j = 0; j < N; j++) { 70 | String letters = BOGGLE_1992[N*i+j]; 71 | int r = StdRandom.uniform(letters.length()); 72 | board[i][j] = letters.charAt(r); 73 | } 74 | } 75 | } 76 | 77 | /** 78 | * Initializes a board from the given filename. 79 | * @param filename the name of the file containing the Boggle board 80 | */ 81 | public BoggleBoard(String filename) { 82 | In in = new In(filename); 83 | M = in.readInt(); 84 | N = in.readInt(); 85 | board = new char[M][N]; 86 | for (int i = 0; i < M; i++) { 87 | for (int j = 0; j < N; j++) { 88 | String letter = in.readString().toUpperCase(); 89 | if (letter.equals("QU")) 90 | board[i][j] = 'Q'; 91 | else if (letter.length() != 1) 92 | throw new IllegalArgumentException("invalid character: " + letter); 93 | else if (ALPHABET.indexOf(letter) == -1) 94 | throw new IllegalArgumentException("invalid character: " + letter); 95 | else 96 | board[i][j] = letter.charAt(0); 97 | } 98 | } 99 | } 100 | 101 | /** 102 | * Initializes a random M-by-N board, according to the frequency 103 | * of letters in the English language. 104 | * @param M the number of rows 105 | * @param N the number of columns 106 | */ 107 | public BoggleBoard(int M, int N) { 108 | this.M = M; 109 | this.N = N; 110 | board = new char[M][N]; 111 | for (int i = 0; i < M; i++) { 112 | for (int j = 0; j < N; j++) { 113 | int r = StdRandom.discrete(FREQUENCIES); 114 | board[i][j] = ALPHABET.charAt(r); 115 | } 116 | } 117 | } 118 | 119 | /** 120 | * Initializes a board from the given 2d character array, 121 | * with 'Q' representing the two-letter sequence "Qu". 122 | * @param a the 2d character array 123 | */ 124 | public BoggleBoard(char[][] a) { 125 | this.M = a.length; 126 | this.N = a[0].length; 127 | board = new char[M][N]; 128 | for (int i = 0; i < M; i++) { 129 | if (a[i].length != N) 130 | throw new IllegalArgumentException("char[][] array is ragged"); 131 | for (int j = 0; j < N; j++) { 132 | if (ALPHABET.indexOf(a[i][j]) == -1) 133 | throw new IllegalArgumentException("invalid character: " + a[i][j]); 134 | board[i][j] = a[i][j]; 135 | } 136 | } 137 | } 138 | 139 | /** 140 | * Returns the number of rows. 141 | * @return number of rows 142 | */ 143 | public int rows() { return M; } 144 | 145 | /** 146 | * Returns the number of columns. 147 | * @return number of columns 148 | */ 149 | public int cols() { return N; } 150 | 151 | /** 152 | * Returns the letter in row i and column j, 153 | * with 'Q' representing the two-letter sequence "Qu". 154 | * @param i the row 155 | * @param j the column 156 | * @return the letter in row i and column j 157 | * with 'Q' representing the two-letter sequence "Qu". 158 | */ 159 | public char getLetter(int i, int j) { 160 | return board[i][j]; 161 | } 162 | 163 | /** 164 | * Returns a string representation of the board, replacing 'Q' with "Qu". 165 | * @return a string representation of the board, replacing 'Q' with "Qu" 166 | */ 167 | public String toString() { 168 | StringBuilder sb = new StringBuilder(M + " " + N + "\n"); 169 | for (int i = 0; i < M; i++) { 170 | for (int j = 0; j < N; j++) { 171 | sb.append(board[i][j]); 172 | if (board[i][j] == 'Q') sb.append("u "); 173 | else sb.append(" "); 174 | } 175 | sb.append("\n"); 176 | } 177 | return sb.toString().trim(); 178 | } 179 | 180 | /** 181 | * Unit tests the BoggleBoard data type. 182 | */ 183 | public static void main(String[] args) { 184 | 185 | // initialize a 4-by-4 board using Hasbro dice 186 | StdOut.println("Hasbro board:"); 187 | BoggleBoard board1 = new BoggleBoard(); 188 | StdOut.println(board1); 189 | StdOut.println(); 190 | 191 | // initialize a 4-by-4 board using letter frequencies in English language 192 | StdOut.println("Random 4-by-4 board:"); 193 | BoggleBoard board2 = new BoggleBoard(4, 4); 194 | StdOut.println(board2); 195 | StdOut.println(); 196 | 197 | // initialize a 4-by-4 board from a 2d char array 198 | StdOut.println("4-by-4 board from 2D character array:"); 199 | char[][] a = { 200 | { 'D', 'O', 'T', 'Y' }, 201 | { 'T', 'R', 'S', 'F' }, 202 | { 'M', 'X', 'M', 'O' }, 203 | { 'Z', 'A', 'B', 'W' } 204 | }; 205 | BoggleBoard board3 = new BoggleBoard(a); 206 | StdOut.println(board3); 207 | StdOut.println(); 208 | 209 | // initialize a 4-by-4 board from a file 210 | String filename = "board-quinquevalencies.txt"; 211 | StdOut.println("4-by-4 board from file " + filename + ":"); 212 | BoggleBoard board4 = new BoggleBoard(filename); 213 | StdOut.println(board4); 214 | StdOut.println(); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /jobinterviewquestions/UnionFind.java: -------------------------------------------------------------------------------- 1 | package jobinterviewquestions; 2 | 3 | import algs4.WeightedQuickUnionUF; 4 | 5 | /** 6 | * Created by Leon on 6/30/15. 7 | */ 8 | public class UnionFind { 9 | /* Question 1 10 | Social network connectivity. 11 | Given a social network containing N members and a log file containing M timestamps at which times pairs of members formed friendships, 12 | design an algorithm to determine the earliest time at which all members are connected 13 | (i.e., every member is a friend of a friend of a friend ... of a friend). 14 | Assume that the log file is sorted by timestamp and that friendship is an equivalence relation. 15 | The running time of your algorithm should be MlogN or better and use extra space proportional to N. */ 16 | private class Log { 17 | int p; 18 | int q; 19 | double time; 20 | } 21 | 22 | public double getTime(Log[] M, int N) { 23 | WeightedQuickUnionUF network = new WeightedQuickUnionUF(N); 24 | 25 | for (int i = 0; i < M.length; i++) { 26 | network.union(M[i].p, M[i].q); 27 | if (network.count() == 1) return M[i].time; 28 | } 29 | return -1; 30 | } 31 | 32 | /* 33 | Question 2 34 | Union-find with specific canonical element. 35 | Add a method find() to the union-find data type so that find(i) returns the largest element in the connected component containing i. 36 | The operations, union(), connected(), and find() should all take logarithmic time or better. 37 | For example, if one of the connected components is {1,2,6,9}, then the find() method should return 9 for each of the four elements in the connected components. 38 | */ 39 | 40 | private class MaxUF{ 41 | private int[] id; 42 | private int[] size; 43 | private int[] largest; 44 | private int count; 45 | 46 | public MaxUF(int N){ 47 | id = new int[N]; 48 | size = new int[N]; 49 | largest = new int[N]; 50 | count = N; 51 | for (int i = 0; i < N; i++) { 52 | id[i] = i; 53 | size[i] = 1; 54 | largest[i] = i; 55 | } 56 | } 57 | 58 | private int root(int i){ 59 | while (i != id[i]){ 60 | id[i] = id[id[i]]; 61 | i = id[i]; 62 | } 63 | return i; 64 | } 65 | 66 | public void union(int p, int q){ 67 | int proot = root(p); 68 | int qroot = root(q); 69 | if (proot == qroot) return; 70 | if (size[proot] <= size[qroot]) { 71 | id[proot] = qroot; 72 | size[qroot] += size[proot]; 73 | if (largest[qroot] < largest[proot]) largest[qroot] = largest[proot]; 74 | } 75 | else { 76 | id[qroot] = proot; 77 | size[proot] += size[qroot]; 78 | if (largest[proot] < largest[qroot]) largest[proot] = largest[qroot]; 79 | } 80 | count--; 81 | } 82 | 83 | public boolean connected(int p, int q){ 84 | return root(p) == root(q); 85 | } 86 | 87 | public int count(){ 88 | return count; 89 | } 90 | 91 | public int find(int i) { 92 | int root = root(i); 93 | return largest[root]; 94 | } 95 | 96 | } 97 | 98 | /* 99 | Question 3 100 | Successor with delete. Given a set of N integers S={0,1,...,N−1} and a sequence of requests of the following form: 101 | Remove x from S 102 | Find the largest of x: the smallest y in S such that y≥x. 103 | design a data type so that all operations (except construction) should take logarithmic time or better. 104 | */ 105 | 106 | private class Successor { 107 | private int[] id; 108 | private int[] size; 109 | private int[] largest; 110 | 111 | public Successor(int N) { 112 | id = new int[N + 1]; 113 | size = new int[N + 1]; 114 | largest = new int[N + 1]; 115 | 116 | for (int i = 0; i <= N; i++) { 117 | id[i] = i; 118 | size[i] = 1; 119 | largest[i] = i; 120 | } 121 | largest[N] = -1; 122 | } 123 | 124 | private int root(int i){ 125 | while (i != id[i]){ 126 | id[i] = id[id[i]]; 127 | i = id[i]; 128 | } 129 | return i; 130 | } 131 | 132 | private void union(int p, int q){ 133 | int proot = root(p); 134 | int qroot = root(q); 135 | if (proot == qroot) return; 136 | if (size[proot] <= size[qroot]) { 137 | id[proot] = qroot; 138 | size[qroot] += size[proot]; 139 | if (largest[qroot] < largest[proot]) largest[qroot] = largest[proot]; 140 | } 141 | else { 142 | id[qroot] = proot; 143 | size[proot] += size[qroot]; 144 | if (largest[proot] < largest[qroot]) largest[proot] = largest[qroot]; 145 | } 146 | } 147 | 148 | public void delete(int i) { 149 | assert i < id.length - 1 && i > 0; 150 | int rootnext = root(i + 1); 151 | if (size[i] <= size[rootnext]) { 152 | id[i] = id[rootnext]; 153 | size[rootnext] += size[i]; 154 | } 155 | else { 156 | id[rootnext] = id[i]; 157 | size[i] += size[rootnext]; 158 | largest[i] = largest[rootnext]; 159 | } 160 | } 161 | 162 | public int find(int i) { 163 | int root = root(i); 164 | return largest[root]; 165 | } 166 | } 167 | 168 | /* 169 | Question 4 170 | Union-by-size. 171 | Develop a union-find implementation that uses the same basic strategy as weighted quick-union 172 | but keeps track of tree height and always links the shorter tree to the taller one. 173 | Prove a lgN upper bound on the height of the trees for N sites with your algorithm. 174 | */ 175 | 176 | private class WeightUFByHeight { 177 | private int[] id; 178 | private int[] size; 179 | private int count; 180 | private int[] largest; 181 | 182 | public WeightUFByHeight(int N){ 183 | id = new int[N]; 184 | size = new int[N]; 185 | largest = new int[N]; 186 | count = N; 187 | for (int i = 0; i < N; i++) { 188 | largest[i] = i; 189 | id[i] = i; 190 | size[i] = 1; 191 | } 192 | } 193 | 194 | private int root(int i){ 195 | while (i != id[i]){ 196 | id[i] = id[id[i]]; 197 | i = id[i]; 198 | } 199 | return i; 200 | } 201 | 202 | public void union(int p, int q){ 203 | int proot = root(p); 204 | int qroot = root(q); 205 | if (proot == qroot) return; 206 | if (size[proot] < size[qroot]) { 207 | id[proot] = qroot; 208 | size[qroot] += size[proot] - 1; 209 | if (largest[qroot] < largest[proot]) largest[qroot] = largest[proot]; 210 | } 211 | else if (size[proot] > size[qroot]){ 212 | id[qroot] = proot; 213 | size[proot] += size[qroot] - 1; 214 | if (largest[proot] < largest[qroot]) largest[proot] = largest[qroot]; 215 | } 216 | else { 217 | id[proot] = qroot; 218 | if (size[proot] > 1) size[qroot] += size[proot] - 1; 219 | else size[qroot] += size[proot]; 220 | if (largest[qroot] < largest[proot]) largest[qroot] = largest[proot]; 221 | } 222 | count--; 223 | } 224 | 225 | public boolean connected(int p, int q){ 226 | return root(p) == root(q); 227 | } 228 | 229 | public int count(){ 230 | return count; 231 | } 232 | 233 | public int find(int i) { 234 | int root = root(i); 235 | return largest[root]; 236 | } 237 | } 238 | 239 | 240 | } 241 | -------------------------------------------------------------------------------- /assignments/baseball/BaseballElimination.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.*; 4 | import stdlib.In; 5 | import stdlib.StdOut; 6 | 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | 10 | /** 11 | * Created by Leon on 8/14/15. 12 | */ 13 | public class BaseballElimination { 14 | private HashMap teamMap; 15 | private int[] wins; 16 | private int[] losses; 17 | private int[] remainings; 18 | private int[][] against; 19 | private FlowNetwork flowNetwork; 20 | private boolean[] eliminated; 21 | private Iterable[] certificate; 22 | private boolean[] cached; 23 | private int N; 24 | 25 | //constructor, take file name as input 26 | public BaseballElimination(String filename) { 27 | In in = new In(filename); 28 | String l = in.readLine(); 29 | N = Integer.parseInt(l); 30 | teamMap = new HashMap(); 31 | wins = new int[N]; 32 | losses = new int[N]; 33 | remainings = new int[N]; 34 | against = new int[N][N]; 35 | eliminated = new boolean[N]; 36 | certificate = new Iterable[N]; 37 | cached = new boolean[N]; 38 | 39 | int i = 0; 40 | while (in.hasNextLine()) { 41 | String line = in.readLine(); 42 | String[] tokens = line.split(" +"); 43 | String team = tokens[0]; 44 | teamMap.put(team, i); 45 | wins[i] = Integer.parseInt(tokens[1]); 46 | losses[i] = Integer.parseInt(tokens[2]); 47 | remainings[i] = Integer.parseInt(tokens[3]); 48 | 49 | for (int j = 0; j < N; j++) { 50 | against[i][j] = Integer.parseInt(tokens[4 + j]); 51 | } 52 | i++; 53 | } 54 | } 55 | //all team names 56 | public Iterable teams() { 57 | return teamMap.keySet(); 58 | } 59 | //check whether one team is eliminated 60 | public boolean isEliminated(String team) { 61 | if (!teamMap.containsKey(team)) throw new IllegalArgumentException(); 62 | int index = getIndex(team); 63 | if (!cached[index]) { 64 | runElimination(team); 65 | cached[index] = true; 66 | } 67 | return eliminated[index]; 68 | } 69 | //certificate teams of elimination 70 | public Iterable certificateOfElimination(String team) { 71 | if (!teamMap.containsKey(team)) throw new IllegalArgumentException(); 72 | int index = getIndex(team); 73 | if (!cached[index]) { 74 | runElimination(team); 75 | cached[index] = true; 76 | } 77 | return certificate[index]; 78 | } 79 | //current wins of one team 80 | public int wins(String team) { 81 | if (!teamMap.containsKey(team)) throw new IllegalArgumentException(); 82 | int index = getIndex(team); 83 | return wins[index]; 84 | } 85 | //current losses of one team 86 | public int losses(String team) { 87 | if (!teamMap.containsKey(team)) throw new IllegalArgumentException(); 88 | int index = getIndex(team); 89 | return losses[index]; 90 | } 91 | //remaining games of one team 92 | public int remaining(String team) { 93 | if (!teamMap.containsKey(team)) throw new IllegalArgumentException(); 94 | int index = getIndex(team); 95 | return remainings[index]; 96 | } 97 | //remaining games between two teams 98 | public int against(String team1, String team2) { 99 | if (!teamMap.containsKey(team1) || !teamMap.containsKey(team2)) throw new IllegalArgumentException(); 100 | int i1 = getIndex(team1); 101 | int i2 = getIndex(team2); 102 | 103 | return against[i1][i2]; 104 | } 105 | //helper function for running trivia elimination process (win1 + remain1 - win2 < 0) 106 | private void runTriviaElimination(String team) { 107 | Bag c = new Bag(); 108 | int index = getIndex(team); 109 | 110 | for (String t : teams()) { 111 | if (!t.equals(team) && compareWins(team, t) < 0) { 112 | c.add(t); 113 | } 114 | } 115 | if (c.size() > 0) { 116 | certificate[index] = c; 117 | eliminated[index] = true; 118 | } 119 | 120 | } 121 | //helper function for computing win1 + remain1 - win2 122 | private int compareWins(String team1, String team2) { 123 | return wins(team1) + remaining(team1) - wins(team2); 124 | } 125 | //helper function for running non trivia elimination using max flow algorithm 126 | private void runNonTriviaElimination(String team) { 127 | String[] indices = constructIndices(team); 128 | constructFlowNetWork(indices); 129 | runFordFulkerson(indices); 130 | } 131 | //helper function for constructing vertices index mapping for teams 132 | private String[] constructIndices(String team) { 133 | String[] indices = new String[N]; 134 | indices[0] = team; 135 | int i = 1; 136 | for (String t: teams()) { 137 | if (!t.equals(team)) indices[i++] = t; 138 | } 139 | return indices; 140 | } 141 | //helper function for constructing flownetwork 142 | private void constructFlowNetWork(String[] indices) { 143 | int V = 2 + (N - 1)*(N- 1); 144 | flowNetwork = new FlowNetwork(V); 145 | 146 | String team = indices[0]; 147 | //let s = 0, t = V - 1; 148 | int v = 1; 149 | for (int i = 1; i < N; i++) { 150 | for (int j = 1; j < N; j++) { 151 | if (i > j) { 152 | v++; 153 | continue; 154 | } 155 | else if (i == j){ 156 | String other = indices[i]; 157 | flowNetwork.addEdge(new FlowEdge(v, V - 1, compareWins(team, other))); 158 | v++; 159 | } 160 | else { 161 | String t1 = indices[i]; 162 | String t2 = indices[j]; 163 | flowNetwork.addEdge(new FlowEdge(0, v, against(t1 ,t2))); 164 | flowNetwork.addEdge(new FlowEdge(v, (i - 1)*(N - 1) + i % N, Double.POSITIVE_INFINITY)); 165 | flowNetwork.addEdge(new FlowEdge(v, (j - 1)*(N - 1) + j % N, Double.POSITIVE_INFINITY)); 166 | v++; 167 | } 168 | } 169 | } 170 | 171 | //System.out.println(flowNetwork); 172 | 173 | 174 | } 175 | //helper function for running ford-fulkerson on the flownetwork, check whether teams are in min-cut and save data in cache 176 | private void runFordFulkerson(String[] indices) { 177 | int V = 2 + (N - 1)*(N - 1); 178 | FordFulkerson ff = new FordFulkerson(flowNetwork, 0, V - 1); 179 | Bag c = new Bag(); 180 | 181 | for (int i = 1; i < N; i++) { 182 | boolean inMinCut = ff.inCut((i - 1)*(N - 1) + i % N); 183 | if (inMinCut) { 184 | c.add(indices[i]); 185 | } 186 | } 187 | 188 | if (c.size() > 0) { 189 | eliminated[getIndex(indices[0])] = true; 190 | certificate[getIndex(indices[0])] = c; 191 | } 192 | 193 | } 194 | //helper function for combining trivia and non trivia elimination process 195 | private void runElimination(String team) { 196 | runTriviaElimination(team); 197 | int index = getIndex(team); 198 | if (N > 2 && !eliminated[index]) { 199 | runNonTriviaElimination(team); 200 | } 201 | } 202 | //helper function for get index for one team 203 | private int getIndex(String team) { 204 | return teamMap.get(team); 205 | } 206 | 207 | public static void main(String[] args) { 208 | BaseballElimination division = new BaseballElimination("./resources/baseball/teams4.txt"); 209 | for (String team : division.teams()) { 210 | if (division.isEliminated(team)) { 211 | StdOut.print(team + " is eliminated by the subset R = { "); 212 | for (String t : division.certificateOfElimination(team)) { 213 | StdOut.print(t + " "); 214 | } 215 | StdOut.println("}"); 216 | } 217 | else { 218 | StdOut.println(team + " is not eliminated"); 219 | } 220 | } 221 | 222 | 223 | } 224 | 225 | 226 | } 227 | -------------------------------------------------------------------------------- /assignments/Boggle/BoggleSolver.java: -------------------------------------------------------------------------------- 1 | package assignments; 2 | 3 | import algs4.Bag; 4 | import algs4.Stack; 5 | import stdlib.In; 6 | 7 | import java.util.HashSet; 8 | import java.util.Iterator; 9 | import java.util.Set; 10 | 11 | /** 12 | * Created by Leon on 8/19/15. 13 | */ 14 | public class BoggleSolver { 15 | private HashSet dictionary; 16 | 17 | private static final int R = 26; 18 | private static final int OFFSET = 65; 19 | //data structure to store dictionary 20 | private Node root; 21 | //data structure Node 22 | private class Node { 23 | private Node[] next = new Node[R]; 24 | private boolean isString; 25 | } 26 | //add key in data structure 27 | private void addNode(String key) { root = addNode(root, key, 0);} 28 | //helper function for adding key 29 | private Node addNode(Node x, String key, int d) { 30 | if (x == null) x = new Node(); 31 | if (d == key.length()) { 32 | if (d > 2) 33 | x.isString = true; 34 | } 35 | else { 36 | char c = key.charAt(d); 37 | x.next[c - OFFSET] = addNode(x.next[c - OFFSET], key, d + 1); 38 | } 39 | return x; 40 | } 41 | //prefix query, given a node 42 | private Node queryNext(Node node, char next) { 43 | return node.next[next - OFFSET]; 44 | } 45 | //DEBUG function 46 | private boolean contains(String key) { 47 | Node x = get(root, key, 0); 48 | if (x == null) return false; 49 | return x.isString; 50 | } 51 | //DEBUG function 52 | private Node get(Node x, String key, int d) { 53 | if (x == null) return null; 54 | if (d == key.length()) return x; 55 | char c = key.charAt(d); 56 | return get(x.next[c - OFFSET], key, d+1); 57 | } 58 | 59 | //data structure to store board graph 60 | private char[] chars; 61 | private static Bag[] HASBRO; 62 | private static Bag[] adjs; 63 | private int V; 64 | //initialize board graph given a board 65 | private void initializeBoardGraph(BoggleBoard board) { 66 | int row = board.rows(); 67 | int col = board.cols(); 68 | V = row*col; 69 | chars = new char[V]; 70 | if (row == 4 && col == 4) this.adjs = HASBRO; 71 | else { 72 | adjs = (Bag[]) new Bag[row*col]; 73 | for (int v = 0; v < V; v++) { 74 | adjs[v] = new Bag(); 75 | addAdj(adjs, v, col, row); 76 | } 77 | } 78 | 79 | for (int v = 0; v < V; v++) { 80 | chars[v] = board.getLetter(v/col, v%col); 81 | } 82 | } 83 | //initialize a 4x4 hasbro board 84 | private void initializeHASBROGraph() { 85 | HASBRO = (Bag[]) new Bag[16]; 86 | for (int v = 0; v < 16; v++) { 87 | HASBRO[v] = new Bag(); 88 | addAdj(HASBRO, v, 4, 4); 89 | } 90 | } 91 | //helper function for adding all adjacent vertices given one vertex 92 | private void addAdj(Bag[] adj,int v, int col, int row) { 93 | if (v % col > 0) { 94 | addEdge(adj, v, v - 1); 95 | if (v / col > 0) addEdge(adj, v, v - col - 1); 96 | if (v / col < row - 1) addEdge(adj, v, v + col - 1); 97 | } 98 | if (v % col < col - 1) { 99 | addEdge(adj, v, v + 1); 100 | if (v / col > 0) addEdge(adj, v, v - col + 1); 101 | if (v / col < row - 1) addEdge(adj, v, v + col + 1); 102 | } 103 | if (v / col > 0) addEdge(adj, v, v - col); 104 | if (v / col < row - 1) addEdge(adj, v, v + col); 105 | } 106 | //helper function for adding one edge 107 | private void addEdge(Bag[] adj, int v, int w) { 108 | adj[v].add(w); 109 | } 110 | //BoardGraph class, for performance test, not used 111 | private static class BoardGraph { 112 | private Bag[] adj; 113 | private int V; 114 | private BoggleBoard board; 115 | private int col; 116 | private int row; 117 | 118 | public BoardGraph(BoggleBoard board) { 119 | this.board = board; 120 | this.col = board.cols(); 121 | this.row = board.rows(); 122 | this.V = col * row; 123 | adj = (Bag[]) new Bag[V]; 124 | addAllEdge(board); 125 | } 126 | 127 | public Iterable adj(int v) { 128 | return adj[v]; 129 | } 130 | 131 | public char getLetter(int v) { 132 | int r = v / col; 133 | int c = v % col; 134 | return board.getLetter(r, c); 135 | } 136 | 137 | public int V() {return V;} 138 | 139 | private void addAllEdge(BoggleBoard board) { 140 | for (int v = 0; v < row*col; v++) { 141 | adj[v] = new Bag(); 142 | addAdj(v); 143 | } 144 | } 145 | 146 | private void addAdj(int v) { 147 | if (v % col > 0) { 148 | addEdge(v, v - 1); 149 | if (v / col > 0) addEdge(v, v - col - 1); 150 | if (v / col < row - 1) addEdge(v, v + col - 1); 151 | } 152 | if (v % col < col - 1) { 153 | addEdge(v, v + 1); 154 | if (v / col > 0) addEdge(v, v - col + 1); 155 | if (v / col < row - 1) addEdge(v, v + col + 1); 156 | } 157 | if (v / col > 0) addEdge(v, v - col); 158 | if (v / col < row - 1) addEdge(v, v + col); 159 | } 160 | 161 | private void addEdge(int v, int w) { 162 | adj[v].add(w); 163 | } 164 | //DEBUG 165 | public String toString() { 166 | StringBuilder s = new StringBuilder(); 167 | String NEWLINE = System.getProperty("line.separator"); 168 | for (int v = 0; v < V; v++) { 169 | s.append(getLetter(v) + ": "); 170 | for (int w : adj[v]) { 171 | s.append(getLetter(w) + " "); 172 | } 173 | s.append(NEWLINE); 174 | } 175 | return s.toString(); 176 | } 177 | } 178 | // Initializes the data structure using the given array of strings as the dictionary. 179 | // (You can assume each word in the dictionary contains only the uppercase letters A through Z.) 180 | public BoggleSolver(String[] dictionary) { 181 | initialize(dictionary); 182 | initializeHASBROGraph(); 183 | } 184 | //helper function for initializing BoggleSolver 185 | private void initialize(String[] dictionary) { 186 | this.dictionary = new HashSet(); 187 | for (String d : dictionary) { 188 | this.dictionary.add(d); 189 | addNode(d); 190 | } 191 | } 192 | // Returns the set of all valid words in the given Boggle board, as an Iterable. 193 | public Iterable getAllValidWords(BoggleBoard board) { 194 | initializeBoardGraph(board); 195 | Set result = new HashSet(); 196 | for (int v = 0; v < V; v++) { 197 | dfs(v, result); 198 | } 199 | return result; 200 | } 201 | //DEBUG function 202 | private Iterable getValidWords(BoggleBoard board, int v) { 203 | long startTime = System.currentTimeMillis(); 204 | BoardGraph bg = new BoardGraph(board); 205 | long endTime = System.currentTimeMillis(); 206 | long totalTime = endTime - startTime; 207 | System.out.println(totalTime / 1000d); 208 | Set result = new HashSet(); 209 | dfs(v, result); 210 | 211 | return result; 212 | } 213 | //helper function for dfs and adding result 214 | private void dfs(int s, Set result) { 215 | //check first char, if not found in trie, return 216 | char start = chars[s]; 217 | Node first = queryNext(root, start); 218 | if (first == null) return; 219 | //initialize iterator for each vertex in bg 220 | Iterator[] adj = (Iterator[]) new Iterator[V]; 221 | for (int v = 0; v < V; v++) 222 | adj[v] = adjs[v].iterator(); 223 | //mark visited vertices to avoid cycle 224 | boolean[] onTrack = new boolean[V]; 225 | onTrack[s] = true; 226 | //track visited trie node 227 | Stack nodes = new Stack(); 228 | nodes.push(first); 229 | //track visited vertices 230 | Stack visited = new Stack(); 231 | visited.push(s); 232 | //track visited prefix 233 | StringBuilder prefix = new StringBuilder(Character.toString(start)); 234 | 235 | //depth first search 236 | while (!visited.isEmpty()) { 237 | int v = visited.peek(); 238 | Node n = nodes.peek(); 239 | if (n != null && n.isString) 240 | result.add(prefix.toString()); 241 | 242 | if (adj[v].hasNext() && n != null) { //if prefix node exists and vertex has adjacent vertices to go 243 | int w = adj[v].next(); 244 | char cw = chars[w]; 245 | if (!onTrack[w]) { 246 | onTrack[w] = true; 247 | visited.push(w); 248 | nodes.push(queryNext(n, cw)); 249 | prefix.append(cw); 250 | } 251 | } 252 | else { 253 | visited.pop(); 254 | nodes.pop(); 255 | onTrack[v] = false; 256 | adj[v] = adjs[v].iterator(); //reset iterator 257 | prefix.setLength(prefix.length() - 1); //remove last char from prefix 258 | } 259 | } 260 | 261 | } 262 | 263 | // Returns the score of the given word if it is in the dictionary, zero otherwise. 264 | // (You can assume the word contains only the uppercase letters A through Z.) 265 | public int scoreOf(String word) { 266 | int len = word.length(); 267 | if (dictionary.contains(word)) { 268 | return scoreOf(len); 269 | } 270 | return 0; 271 | } 272 | //helper function for computing score 273 | private int scoreOf(int len) { 274 | if (len < 3) return 0; 275 | else if (len < 5) return 1; 276 | else if (len == 5) return 2; 277 | else if (len == 6) return 3; 278 | else if (len == 7) return 5; 279 | else return 11; 280 | } 281 | 282 | public static void main(String[] args) { 283 | //char[][] a = { 284 | // { 'D', 'O', 'T', 'Y' }, 285 | // { 'T', 'R', 'S', 'F' }, 286 | // { 'M', 'X', 'M', 'O' }, 287 | // { 'Z', 'A', 'B', 'W' } 288 | //}; 289 | 290 | BoggleBoard[] board = new BoggleBoard[1000]; 291 | for (int i = 0; i < 1000; i++) { 292 | board[i] = new BoggleBoard(); 293 | } 294 | //StdOut.println(board); 295 | //BoardGraph bg = new BoardGraph(board); 296 | //StdOut.println(bg); 297 | 298 | //String[] dictionary = {"DOT", "ROT", "ZAXMOFYSORT", "BA", "SF", "FS"}; 299 | In dictIn = new In("./resources/boggle/dictionary-algs4.txt"); 300 | String[] dictionary = dictIn.readAllStrings(); 301 | BoggleSolver bs = new BoggleSolver(dictionary); 302 | //System.out.println(bs.contains("TEAM")); 303 | long startTime = System.nanoTime(); 304 | for (BoggleBoard b : board) { 305 | bs.getAllValidWords(b); 306 | } 307 | //Iterable result = bs.getAllValidWords(board); 308 | //for (String s : result) { 309 | //System.out.print(bs.scoreOf(s)); 310 | // System.out.println(" " + s); 311 | //} 312 | long endTime = System.nanoTime(); 313 | long totalTime = endTime - startTime; 314 | System.out.println(totalTime / 1000000d); 315 | } 316 | } 317 | --------------------------------------------------------------------------------