diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml new file mode 100644 index 0000000000..f9412d07c3 --- /dev/null +++ b/.github/workflows/gradle.yml @@ -0,0 +1,19 @@ +name: Java CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build with Gradle + run: ./gradlew build diff --git a/build.gradle b/build.gradle index 7b91fb79f6..c1e940cf9f 100644 --- a/build.gradle +++ b/build.gradle @@ -23,4 +23,5 @@ dependencies { compile 'com.google.code.gson:gson:2.8.0' compile 'junit:junit:4.12' testCompile group: 'junit', name: 'junit', version:'4.12' + implementation 'org.apache.commons:commons-lang3:3.6' } diff --git a/src/main/java/com/company/autonomic/phone/MaxDistinctElements.java b/src/main/java/com/company/autonomic/phone/MaxDistinctElements.java new file mode 100644 index 0000000000..2fe4da2f97 --- /dev/null +++ b/src/main/java/com/company/autonomic/phone/MaxDistinctElements.java @@ -0,0 +1,79 @@ +package com.company.autonomic.phone; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.PriorityQueue; + +public class MaxDistinctElements { + + /** + * Maximum distinct elements after removing k elements + * + *

Given an array arr[] containing n elements. The problem is to find maximum number of + * distinct elements (non-repeating) after removing k elements from the array. Note: 1 <= k <= n. + * + *

Examples: + * + *

Input : arr[] = {5, 7, 5, 5, 1, 2, 2}, k = 3 Output : 4 Remove 2 occurrences of element 5 + * and 1 occurrence of element 2. + * + *

Input : arr[] = {1, 2, 3, 4, 5, 6, 7}, k = 5 Output : 2 + * + *

Input : arr[] = {1, 2, 2, 2}, k = 1 Output : 1 + * + *

Approach: Following are the steps: + * + *

Create a hash table to store the frequency of each element. Insert frequency of each element + * in a max heap. Now, perform the following operation k times. Remove an element from the max + * heap. Decrement its value by 1. After this if element is not equal to 0, then again push the + * element in the max heap. After the completion of step 3, the number of elements in the max heap + * is the required answer. + * + *

High level: Reducing the most frequent elements to get max distinct element number. Mid + * -level: Insert the frequencies of each, do K times of reducing the frequency on the top of the + * max heap. + */ + public static int maxDistinctElementNumber(int[] input, int k) { + Map freqMap = new HashMap<>(); + PriorityQueue maxHeap = new PriorityQueue<>(Collections.reverseOrder()); + + // Init the frequency map + for (int num : input) { + Integer freq = freqMap.get(num); + if (freq == null) { + freq = 0; + } + freq++; + freqMap.put(num, freq); + } + + for (Map.Entry e : freqMap.entrySet()) { + maxHeap.offer(e.getValue()); + } + + for (int i = k; i > 0; i--) { + Integer freq = maxHeap.poll(); + freq--; + if (freq > 0) { + maxHeap.offer(freq); + } + } + return maxHeap.size(); + } + + public static void main(String[] args) { + int[] arr1 = {5, 7, 5, 5, 1, 2, 2}; + int k1 = 3; + int[] arr2 = {1, 2, 3, 4, 5, 6, 7}; + int k2 = 5; + int[] arr3 = {1, 2, 2, 2}; + int k3 = 1; + System.out.println( + "For arr1 and k1 Maximum distinct elements = " + maxDistinctElementNumber(arr1, k1)); + System.out.println( + "For arr2 and k2 Maximum distinct elements = " + maxDistinctElementNumber(arr2, k2)); + System.out.println( + "For arr3 and k3 Maximum distinct elements = " + maxDistinctElementNumber(arr3, k3)); + } +} diff --git a/src/main/java/com/company/c3ai/phone/CounterVirus.java b/src/main/java/com/company/c3ai/phone/CounterVirus.java new file mode 100644 index 0000000000..5f2d0615a4 --- /dev/null +++ b/src/main/java/com/company/c3ai/phone/CounterVirus.java @@ -0,0 +1,64 @@ +package com.company.c3ai.phone; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CounterVirus { + + public static void main(String[] args) { + int[] tcpPacket = new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + System.out.println(Arrays.toString(tcpPacket)); + iAmVirus(tcpPacket); + System.out.println(Arrays.toString(tcpPacket)); + findComplementIndex(tcpPacket).forEach(i -> System.out.print(i + " ")); + System.out.println(); + changeMeBack(tcpPacket); + System.out.println(Arrays.toString(tcpPacket)); + } + + private static void iAmVirus(int[] tcpPacket) { + int n = tcpPacket.length; + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if ((i + 1) * (j + 1) <= n) { + tcpPacket[(i + 1) * (j + 1) - 1] = complement(tcpPacket[(i + 1) * (j + 1) - 1]); + // System.out.print(Arrays.toString(tcpPacket)); + // System.out.print(" "); + // System.out.println((i + 1) * (j + 1)); + } else { + break; + } + } + } + } + + private static int complement(int i) { + return i == 0 ? 1 : 0; + } + + private static List findComplementIndex(int[] tcpPacket) { + List res = new ArrayList<>(); + for (int i = 0; i < tcpPacket.length; i++) { + if (tcpPacket[i] == 1) { + res.add(i); + } + } + return res; + } + + /** + * Complement the digit at 0,3,8,15,24..... + * @param tcpPacket given tcp packet + */ + private static void changeMeBack(int[] tcpPacket) { + // write your code here + int index = 0; + int i = 1; + while (index < tcpPacket.length) { + tcpPacket[index] = complement(tcpPacket[index]); + index += i * 2 + 1; + i++; + } + } +} diff --git a/src/main/java/com/company/google/topmedium/leet84/_84LargestRectangleHistogram.java b/src/main/java/com/company/google/topmedium/leet84/_84LargestRectangleHistogram.java new file mode 100644 index 0000000000..077529c43e --- /dev/null +++ b/src/main/java/com/company/google/topmedium/leet84/_84LargestRectangleHistogram.java @@ -0,0 +1,72 @@ +package com.company.google.topmedium.leet84; + +import static org.junit.Assert.assertEquals; + +import java.util.Deque; +import java.util.LinkedList; + +public class _84LargestRectangleHistogram { + + /** + * Leetcode 84: Largest Rectangle in histograms + * + *

Given n non-negative integers representing the histogram's bar height where the width of + * each bar is 1, find the area of largest rectangle in the histogram. + * + *

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]. The largest + * rectangle is shown in the shaded area, which has area = 10 unit. + * + *

For example, Given heights = [2,1,5,6,2,3], return 10. + * + *

C: + * + *

What is maximum area supported in this quesiont? Within Integer' data range + * + *

Is there any negative height? A: + * + *

assume the maximum area is less than Integer.MAX_VALUE + * + *

R: + * + *

Use a stack to maintain a series of monolithtic increasing histrograms's index. Only + * monolithtic increasing histogram can produce more rectangle area. + * + *

When we meet decrease histogram: heights[i - 1] > heights[i], pop the stack top, and + * calculate the area with the following formula: area = (i - stock[top - 1] - 1) * + * heights[stack[top]] T: + * + *

null, empty -> 0 + * + *

[1,2,3,4] -> 6 + * + *

[1,2,3,4,3] -> 9 + * + *

[3,2,1] -> 4 + */ + public static int largestRectangleArea(int[] heights) { + if (heights == null || heights.length == 0) { + return 0; + } + Deque stack = new LinkedList<>(); + int maxArea = 0; + for (int i = 0; i <= heights.length; i++) { + int cur = (i == heights.length) ? 0 : heights[i]; + while (!stack.isEmpty() && heights[stack.peekLast()] >= cur) { + int height = heights[stack.pollLast()]; + int left = stack.isEmpty() ? 0 : stack.peekLast() + 1; + maxArea = Math.max(maxArea, height * (i - left)); + } + stack.addLast(i); + } + return maxArea; + } + + public static void main(String[] args) { + assertEquals(0, largestRectangleArea(null)); + assertEquals(0, largestRectangleArea(new int[] {})); + assertEquals(1, largestRectangleArea(new int[] {1})); + assertEquals(6, largestRectangleArea(new int[] {1, 2, 3, 4})); + assertEquals(9, largestRectangleArea(new int[] {1, 2, 3, 4, 3})); + assertEquals(4, largestRectangleArea(new int[] {3, 2, 1})); + } +} diff --git a/src/main/java/com/company/google/topmedium/leet84/uptake/_85MaxRectangleMatrix.java b/src/main/java/com/company/google/topmedium/leet84/uptake/_85MaxRectangleMatrix.java new file mode 100644 index 0000000000..85ff1862b5 --- /dev/null +++ b/src/main/java/com/company/google/topmedium/leet84/uptake/_85MaxRectangleMatrix.java @@ -0,0 +1,78 @@ +package com.company.google.topmedium.leet84.uptake; + + +import static com.company.google.topmedium.leet84._84LargestRectangleHistogram.largestRectangleArea; +import static org.junit.Assert.assertEquals; + +public class _85MaxRectangleMatrix { + + /** + * 85. Maximal Rectangle + * + *

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only + * 1's and return its area. + * + *

For example, given the following matrix: + * + *

1 0 1 0 0 + * 1 0 1 1 1 + * 1 1 1 1 1 + * 1 0 0 1 0 + * + * Return 6. + *

C: + * + *

What is the data type of the elements? char or int? -> char + * + *

How big can the matrix be? The area of the matrix can be fit into memory A: + * + *

The matrix cannot be null/ empty., and at least has one element. R: + * + *

1. rows as X axis, and columns as Y axis. The 1 rectangle can be considered as the a series + * of histograms based on current row + * + *

Thus the matrix can be converted to 4 histograms: + * + *

1st row: [1, 0 , 1, 0, 0] + * + *

2nd row: [2, 0 , 2, 1, 1] + * + *

3rd row: [3, 1 , 3, 2, 2] + * + *

4th row: [4, 0 , 0, 3, 0] + * + *

2. Apply the monolithic increasing stack to get the max area among the histogram + * T:

[[1]], problem example + */ + + public static int maxRetangleArea(char[][] A) { + int[][] H = new int[A.length][A[0].length]; + for (int row = 0; row < A.length; row++) { + for (int col = 0; col < A[0].length; col++) { + if (row == 0) { + H[row][col] = (A[row][col] - '0'); + } else { + H[row][col] = (A[row][col] - '0') == 0 ? 0 : (H[row - 1][col]) + 1; + } + } + } + int maxArea = 0; + for (int[] heights : H) { + maxArea = Math.max(maxArea, largestRectangleArea(heights)); + } + return maxArea; + } + + public static void main(String[] args) { + char[][] test1 = new char[][] {{'1'}}; + char[][] test2 = + new char[][] { + {'1', '0', '1', '0', '0'}, + {'1', '0', '1', '1', '1'}, + {'1', '1', '1', '1', '1'}, + {'1', '0', '0', '1', '0'} + }; + assertEquals(1, maxRetangleArea(test1)); + assertEquals(6, maxRetangleArea(test2)); + } +} diff --git a/src/main/java/com/company/google/topmedium/maxsquare/similar/_764LargestPlusSign.java b/src/main/java/com/company/google/topmedium/maxsquare/similar/_764LargestPlusSign.java new file mode 100644 index 0000000000..eaa2acc2c8 --- /dev/null +++ b/src/main/java/com/company/google/topmedium/maxsquare/similar/_764LargestPlusSign.java @@ -0,0 +1,73 @@ +package com.company.google.topmedium.maxsquare.similar; + + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +class _764LargestPlusSign { + + /** + * In a 2D grid from (0, 0) to (N-1, N-1), every cell contains a 1, except those cells in the + * given list mines which are 0. What is the largest axis-aligned plus sign of 1s contained in the + * grid? Return the order of the plus sign. If there is none, return 0. + * + *

An "axis-aligned plus sign of 1s of order k" has some center grid[x][y] = 1 along with 4 + * arms of length k-1 going up, down, left, and right, and made of 1s. This is demonstrated in the + * diagrams below. Note that there could be 0s or 1s beyond the arms of the plus sign, only the + * relevant area of the plus sign is checked for 1s. + * + *

Input: N = 5, mines = [[4, 2]] Output: 2 Explanation: 11111 11111 11111 11111 11011 In the + * above grid, the largest plus sign can only be order 2. + */ + public static int orderOfLargestPlusSign(int N, int[][] mines) { + int[][] dp = new int[N][N]; + + for (int[] row : dp) { + Arrays.fill(row, N); + } + + for (int[] m : mines) { + dp[m[0]][m[1]] = 0; + } + + for (int i = 0; i < N; i++) { + + int left = 0; + for (int j = 0; j < N; j++) { + left = dp[i][j] == 0 ? 0 : left + 1; + dp[i][j] = Math.min(dp[i][j], left); + } + + int right = 0; + for (int j = N - 1; j >= 0; j--) { + right = dp[i][j] == 0 ? 0 : right + 1; + dp[i][j] = Math.min(dp[i][j], right); + } + + int top = 0; + for (int j = 0; j < N; j++) { + top = dp[j][i] == 0 ? 0 : top + 1; + dp[j][i] = Math.min(dp[j][i], top); + } + + int bottom = 0; + for (int j = N - 1; j >= 0; j--) { + bottom = dp[j][i] == 0 ? 0 : bottom + 1; + dp[j][i] = Math.min(dp[j][i], bottom); + } + } + + int res = 0; + for (int i = 0; i < N; i++) { + for (int j = 0; j < N; j++) { + res = Math.max(res, dp[i][j]); + } + } + return res; + } + + public static void main(String[] args) { + assertEquals(2, orderOfLargestPlusSign(5, new int[][] {{4, 2}})); + } +} \ No newline at end of file diff --git a/src/main/java/com/company/samsara/box/Box.java b/src/main/java/com/company/samsara/box/Box.java new file mode 100644 index 0000000000..88e0d837eb --- /dev/null +++ b/src/main/java/com/company/samsara/box/Box.java @@ -0,0 +1,117 @@ +package com.company.samsara.box; + +import java.util.HashMap; +import java.util.Map; +import java.util.PriorityQueue; +import org.apache.commons.lang3.StringUtils; + +/** + * PART 1: Implement a representation of valuable with two fields id and name. + * + *

PART 2: Implement a representation of box, which is used as a container of valuables. + * Implement two methods. First is to add a valuable to the box (given id as input). Second is to + * remove a valuable from the box(given valuable object as input) + * + *

PART3: Add an maximum size bar to the representation of box. Modify the add method so that if + * the total size of valuables in the box will exceed the box size bar, do not add and print an + * error message. Otherwise, add the valuable into the box. + * + *

PART 4: Implement a method to output the maximum valuable-size in the box whenever the method + * is called + */ +public class Box { + + private int sizeBar; + private int currentSize; + private PriorityQueue maxValuables; + private Map contentMap; + + public Box(int sizeBar) { + if (sizeBar <= 0) { + throw new IllegalArgumentException( + "Size bar of a box cannot be smaller thant or equal to zero"); + } + this.sizeBar = sizeBar; + this.currentSize = 0; + maxValuables = new PriorityQueue<>((a, b) -> (b.size - a.size)); + contentMap = new HashMap<>(); + } + + public void addValuable(Valuable valuable) { + if (valuable == null) { + throw new IllegalArgumentException("added valuable cannot be null"); + } + + if (contentMap.containsKey(valuable.id)) { + throw new IllegalArgumentException("valuable is already in the box"); + } + + if (currentSize + valuable.size > sizeBar) { + throw new IllegalArgumentException( + String.format( + "adding this valuable with size %d will exceeds the box' size bar %d", + valuable.size, sizeBar)); + } + + contentMap.put(valuable.id, valuable); + maxValuables.offer(valuable); + currentSize += valuable.size; + System.out.println( + "Added " + + valuable.toString() + + ", current box size: " + + currentSize + + " maxValueSize: " + + getMaxValuableSize()); + } + + public void removeValuable(int id) { + if (!contentMap.containsKey(id)) { + throw new IllegalArgumentException("valuable is no in the box"); + } + Valuable removed = contentMap.remove(id); + maxValuables.remove(removed); + currentSize -= removed.size; + System.out.println( + "Removed " + + removed.toString() + + ", current box size: " + + currentSize + + " maxValueSize: " + + getMaxValuableSize()); + } + + public int getMaxValuableSize() { + if (maxValuables.isEmpty()) { + return 0; + } else { + return maxValuables.peek().size; + } + } + + public static void main(String[] args) { + + Valuable v1 = new Valuable(1, "valuable 1", 1); + Valuable v10 = new Valuable(2, "valuable 10", 10); + Valuable v20 = new Valuable(3, "valuable 20", 20); + Valuable v29 = new Valuable(4, "valuable 29", 29); + Valuable v5 = new Valuable(5, "valuable 5", 5); + Valuable v9 = new Valuable(6, "valuable 9", 9); + + Box aBox = new Box(30); + try { + aBox.addValuable(v1); + aBox.addValuable(v10); + // aBox.addValuable(v20); + aBox.removeValuable(v10.id); + aBox.addValuable(v29); + aBox.removeValuable(v29.id); + aBox.addValuable(v5); + aBox.addValuable(v10); + aBox.addValuable(v9); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + } + } +} + diff --git a/src/main/java/com/company/samsara/box/Valuable.java b/src/main/java/com/company/samsara/box/Valuable.java new file mode 100644 index 0000000000..7e33f0b9d5 --- /dev/null +++ b/src/main/java/com/company/samsara/box/Valuable.java @@ -0,0 +1,26 @@ +package com.company.samsara.box; + +import org.apache.commons.lang3.StringUtils; + +class Valuable { + int id; + String name; + int size; + + public Valuable(int id, String name, int size) { + if (StringUtils.isBlank(name)) { + throw new IllegalArgumentException("Valuabe cannot be blank"); + } + if (size <= 0) { + throw new IllegalArgumentException("Valuabe size cannot be smaller than or equal to 0"); + } + this.id = id; + this.name = name; + this.size = size; + } + + @Override + public String toString() { + return "[id = " + id + ", name = " + name + ", size = " + size + "]"; + } +} diff --git a/src/main/java/com/company/servicenow/phone/SliceMatrix.java b/src/main/java/com/company/servicenow/phone/SliceMatrix.java new file mode 100644 index 0000000000..ec6d852a43 --- /dev/null +++ b/src/main/java/com/company/servicenow/phone/SliceMatrix.java @@ -0,0 +1,75 @@ +package com.company.servicenow.phone; + +import java.util.HashSet; +import java.util.Set; + +public class SliceMatrix { + + /** + * Write a function to slice the matrix with given row numbers and given columns numbers + */ + public static void main(String[] args) { + int[][] test = + new int[][] { + new int[] {1, 1, 1, 1}, + new int[] {0, 0, 0, 0}, + new int[] {2, 1, 3, 3}, + new int[] {1, 2, 4, 4} + }; + int[] rows = new int[] {0, 1}; + int[] cols = new int[] {1, 2}; + // rows + // 0 [1 1 1 1 + // 1 0 0 0 0 + // 2 1 3 3 ==> [2 3 + // 1 2 4 4] 1 4] + // cols 1 2 + int[][] result = findSlicedMatrix(test, rows, cols); + for (int[] r : result) { + for (int num : r) { + System.out.print(num + " "); + } + System.out.println(); + } + } + + /** + * Assumption: M, rows, cols are not null nor empty. + * High level: use set to check if current row or column should be skipped. Use pointer to create new result 2D-array + * Time: (N*M), Space(rows.length + cols.length) + */ + public static int[][] findSlicedMatrix(int[][] M, int[] rows, int[] cols) { + // todo: validate input + int totalRows = M.length; + int totalCols = M[0].length; + int remainRows = totalRows - rows.length; + int remainCols = totalCols - cols.length; + int[][] res = new int[remainRows][remainCols]; + + // find the remaining row index and col index in rows and cols, + Set slicedRows = new HashSet<>(); + Set slicedCols = new HashSet<>(); + + for (int row : rows) { + slicedRows.add(row); + } + for (int col : cols) { + slicedCols.add(col); + } + + for (int i = 0, curRow = 0; i < totalRows; i++) { + if (!slicedRows.contains(i)) { + for (int j = 0, curCol = 0; j < totalCols; j++) { + if (!slicedCols.contains(j)) { + if (curRow < remainRows && curCol < remainCols) { + res[curRow][curCol] = M[i][j]; + } + curCol++; + } + } + curRow++; + } + } + return res; + } +} diff --git a/src/main/java/com/company/smartnews/onsite/DifferentWaysToAddParenthesis.java b/src/main/java/com/company/smartnews/onsite/DifferentWaysToAddParenthesis.java new file mode 100644 index 0000000000..7d4220179b --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/DifferentWaysToAddParenthesis.java @@ -0,0 +1,59 @@ +package com.company.smartnews.onsite; + +import java.util.ArrayList; +import java.util.List; + +public class DifferentWaysToAddParenthesis { + + public static void main(String[] args) { + String test1 = "2-1-1"; + System.out.println(findWays(test1).toString()); + String test2 = "2*3-4*5"; + System.out.println(findWays(test2).toString()); + } + + public static List findWays(String input) { + String[] nums = input.split("[*,+,-]"); + char[] operators = input.replaceAll("[0-9]", "").toCharArray(); + List[][] mem = new List[nums.length][nums.length]; + return dfs(nums, operators, 0, nums.length - 1, mem); + } + + private static List dfs( + String[] nums, char[] operators, int start, int end, List[][] mem) { + if (mem[start][end] != null) { + return mem[start][end]; + } + + if (start == end) { + List baseCase = new ArrayList<>(); + baseCase.add(Integer.parseInt(nums[start])); + mem[start][end] = baseCase; + return baseCase; + } + + List result = new ArrayList<>(); + for (int k = start; k < end; k++) { + List group1 = dfs(nums, operators, start, k, mem); + List group2 = dfs(nums, operators, k + 1, end, mem); + for (Integer num1 : group1) { + for (Integer num2 : group2) { + result.add(calcuate(operators[k], num1, num2)); + } + } + } + mem[start][end] = result; + return result; + } + + private static Integer calcuate(char operator, Integer nums1, Integer nums2) { + switch (operator) { + case '*': + return nums1 * nums2; + case '+': + return nums1 + nums2; + default: + return nums1 - nums2; + } + } +} diff --git a/src/main/java/com/company/smartnews/onsite/KthLargest.java b/src/main/java/com/company/smartnews/onsite/KthLargest.java new file mode 100644 index 0000000000..1e6bfb3e47 --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/KthLargest.java @@ -0,0 +1,164 @@ +package com.company.smartnews.onsite; + +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.PriorityQueue; + +public class KthLargest { + + public static void main(String[] args) { + // int[] nums1 = new int[]{3,2,5,1,4}; + // assertTrue(4 == maxHeapSolution(nums1, 2)); + // assertTrue(4 == minHeapSolution(nums1, 2)); + // assertTrue(4 == quickSelectSolution(nums1, 2)); + + int[] nums2 = + new int[]{ + 15, 44, 16, 43, 47, 47, 45, 27, 46, 2, 28, 12, 49, 22, 36, 12, 6, 48, 28, 19, 18, 34, + 46, + 38, 42, 3, 21, 3, 54, 35, 21, 54, 13, 46, 50, 23, 53, 43, 5, 48, 40, 48, 10, 31, 15, 35, + 50, 8, 48, 55, 52, 18, 54, 16, 35, 4, 43, 55, 34, 13, 5, 13, 27, 41, 19, 22, 21, 26, 48, + 4, 15, 1, 45, 51, 13, 49, 22, 33, 18, 18, 52, 27, 6, 41, 7, 11, 48, 17, 37, 31, 42, 3, + 45, + 22, 6, 45, 42, 5, 28, 39, 35, 30, 24, 21, 49, 49, 47, 54, 28, 42, 40, 26, 47, 8, 28, 1, + 44, 4, 45, 23, 49, 53, 12, 48, 16, 27, 36, 21, 18, 41, 43, 9, 55, 27, 37, 41, 5, 43, 12, + 45, 0, 34, 19, 48, 14, 22, 43, 14, 13, 38, 15, 7, 41, 8, 37, 13, 45, 31, 47, 38, 45, 38, + 50, 44, 20, 40, 39, 38, 26, 29, 24, 10, 30, 23, 53, 38, 39, 3, 37, 4, 15, 22, 29, 4, 5, + 4, + 4, 19, 35, 30, 30, 49, 16, 32, 36, 26, 37, 53, 46, 28, 24, 13, 12, 29, 2, 36, 21, 19, + 15, + 11, 22, 10, 30, 29, 40, 14, 17, 39, 36, 17, 23, 39, 13, 29, 51, 8, 55, 10, 10, 47, 39, + 1, + 46, 27, 18, 7, 49, 38, 27, 14, 26, 35, 5, 46, 54, 12, 18, 30, 11, 6, 29, 52, 44, 38, 51, + 22, 26, 24, 41, 13, 39, 27, 0, 36, 38, 7, 37, 7, 9, 25, 4, 8, 52, 33, 46, 33, 42, 43, + 17, + 23, 20, 23, 41, 8, 47, 16, 48, 46, 35, 35, 24, 0, 17, 12, 40, 52, 11, 16, 7, 33, 6, 21, + 30, 32, 55, 52, 52, 28, 11, 35, 39, 15, 27, 47, 52, 0, 11, 41, 50, 10, 13, 10, 5, 40, + 21, + 0, 27, 12, 39, 20, 27, 39, 19, 28, 5, 51, 45, 19, 3, 1, 15, 53, 31, 45, 36, 33, 22, 4, + 22, + 20, 30, 7, 54, 13, 19, 48, 32, 13, 38, 9, 4, 22, 26, 22, 43, 5, 47, 14, 15, 21, 15, 48, + 10, 15, 47, 22, 9, 52, 4, 16, 22, 47, 9, 13, 44, 15, 5, 19, 2, 55, 36, 49, 25, 52, 21, + 5, + 19, 46, 2, 51, 45, 12, 54, 47, 47, 23, 17, 26, 52, 36, 49, 4, 42, 18, 20, 22, 47, 18, + 37, + 28, 19, 11, 21, 13, 37, 51, 2, 43, 36, 43, 0, 40, 50, 27, 40, 41, 31, 41, 53, 2, 17, 4, + 35, 52, 22, 25, 21, 16, 5, 41, 54, 5, 40, 3, 38, 12, 10, 53, 48, 28, 9, 7, 46, 28, 3, 9, + 44, 29, 39, 3, 41, 15, 29, 30, 47, 21, 12, 27, 53, 7, 34, 53, 53, 50, 53, 23, 46, 52, + 40, + 21, 3, 46, 49, 17, 14, 36, 10, 54, 51, 22, 25, 34, 49, 49, 26, 45, 45, 17, 30, 19, 6, + 49, + 41, 9, 19, 25, 51, 23, 55, 11, 0, 1, 13, 26, 15, 41, 38, 19, 51, 21, 11, 8, 55, 25, 21, + 15, 18, 15, 48, 4, 37, 36, 5, 45, 13, 13, 16, 26, 0, 41, 8, 51, 20, 38, 28, 46, 3, 37, + 52, + 6, 24, 11, 18, 39, 25, 48, 16, 41, 50, 44, 48, 7, 29, 14, 15, 28, 7, 46, 15, 16, 46, 20, + 35, 6, 27, 10, 17, 1, 42, 30, 37, 41, 37, 52, 55, 4, 6, 17, 27, 33, 45, 37, 11, 29, 16, + 42, 33, 39, 35, 33, 30, 25, 37, 6, 25, 22, 43, 31, 42, 25, 15, 27, 19, 15, 10, 1, 45, + 24, + 23, 17, 17, 33, 12, 53, 30, 44, 30, 2, 30, 8, 45, 49, 48, 46, 52, 13, 41, 29, 46, 39, + 50, + 51, 19, 55, 36, 29, 23, 8, 11, 49, 43, 45, 51, 2, 41, 53, 6, 38, 52, 26, 45, 0, 55, 14, + 42, 25, 10, 4, 39, 5, 47, 42, 55, 37, 35, 53, 14, 27, 54, 41, 19, 34, 38, 43, 22, 41, + 23, + 12, 13, 17, 36, 23, 41, 15, 34, 24, 44, 21, 3, 25, 10, 14, 43, 16, 35, 45, 1, 22, 26, + 20, + 5, 8, 37, 42, 47, 1, 2, 33, 2, 21, 8, 36, 50, 6, 45, 40, 48, 16, 12, 1, 55, 0, 53, 51, + 35, + 19, 14, 3, 21, 33, 2, 54, 33, 2, 18, 53, 34, 19, 23, 32, 27, 39, 13, 48, 27, 12, 7, 50, + 16, 49, 35, 27, 12, 29, 6, 34, 7, 18, 50, 6, 49, 24, 1, 18, 53, 27, 36, 0, 37, 42, 51, + 12, + 38, 8, 29, 38, 11, 24, 4, 2, 15, 19, 1, 25, 9, 30, 50, 30, 8, 15, 50, 52, 25, 8, 29, 44, + 7, 41, 30, 45, 9, 23, 20, 49, 15, 16, 48, 34, 10, 44, 52, 22, 4, 6, 2, 8, 23, 13, 39, 7, + 31, 29, 4, 35, 43, 2, 33, 34, 24, 41, 38, 47, 5, 38, 28, 34, 1, 44, 14, 13, 12, 8, 6, 0, + 24, 9, 4, 39, 37, 32, 18, 38, 15, 29, 14, 11, 40, 34, 12, 16, 7, 7, 50, 18, 24, 30, 15, + 13, 41, 42, 47, 22, 17, 14, 38, 46, 45, 22, 12, 12, 12, 25, 11, 24, 41, 8, 51, 51, 25, + 46, + 15, 13, 47, 38, 20, 0, 21, 7, 30, 49, 42, 43, 53, 24, 19, 17, 46, 50, 15, 33, 1, 42, 14, + 55, 26, 17, 41, 39, 23, 46, 35, 39, 16, 16, 37, 50, 38, 24, 20, 32, 51, 22, 53, 50, 10, + 39, 4, 2, 27, 1, 25, 18, 40, 50, 9, 35, 37, 27, 37, 39, 29, 2, 38, 32, 6, 30, 32, 4, 43, + 46, 21, 9, 40, 45, 49, 34, 37, 4, 55, 19, 47, 3, 42, 33, 13, 43, 3, 3, 22, 49 + }; + int minHeapResult = minHeapSolution(nums2, 5); + System.out.println("minHeap Result: " + minHeapResult); + assertTrue(minHeapResult == maxHeapSolution(nums2, 5)); + assertTrue(minHeapResult == quickSelectSolution(nums2, 5)); + } + + // Time: (n + k)logn, Space o(n) + public static Integer maxHeapSolution(int[] nums, int k) { + PriorityQueue maxHeap = new PriorityQueue<>(11, Collections.reverseOrder()); + for (int i = 0; i < nums.length; i++) { // nlogn + maxHeap.offer(nums[i]); + } + while (k > 1) { // k*logn + maxHeap.poll(); + k--; + } + return maxHeap.peek(); + } + + // Time( k*logk + (n - k)* 2*logK = (2n-k)logk = O(n-k)logk, Space O(K) + public static Integer minHeapSolution(int[] nums, int k) { + PriorityQueue minHeap = new PriorityQueue<>(); + for (int i = 0; i < nums.length; i++) { + if (i < k) { // k + minHeap.offer(nums[i]); // logk + } else { + if (nums[i] > minHeap.peek()) { // (n-k) + minHeap.poll(); // logK + minHeap.offer(nums[i]); // logK + } + } + } + return minHeap.peek(); + } + + public static int quickSelectSolution(int[] nums, int k) { + int n = nums.length; + quickSelect(nums, 0, n - 1, n - k); // K-th largest == (N - K)-th smallest + return nums[n - k]; + } + + // Time: O(N) Space:O(logN) + private static void quickSelect(int[] nums, int left, int right, int target) { + int mid = partition(nums, left, right); + if (mid == target) { + return; + } else if (mid < target) { + quickSelect(nums, mid + 1, right, target); + } else { // mid > target + quickSelect(nums, left, mid - 1, target); + } + } + + private static int partition(int[] nums, int left, int right) { + int pivotIndex = pivotIndex(left, right); + mySwap(nums, pivotIndex, right); + int pivot = nums[right]; + int start = left; + int end = right - 1; + while (start <= end) { + if (nums[start] < pivot) { + start++; + } else if (nums[end] >= pivot) { + end--; + } else { + mySwap(nums, start++, end--); + } + } + mySwap(nums, start, right); + return start; + } + + private static int pivotIndex(int left, int right) { + int pivotIndnex = left + (int) (Math.random() * (right - left + 1)); + return pivotIndnex; + } + + private static void mySwap(int[] nums, int left, int right) { + int tmp = nums[left]; + nums[left] = nums[right]; + nums[right] = tmp; + } +} diff --git a/src/main/java/com/company/smartnews/onsite/MergedKSortedArrays.java b/src/main/java/com/company/smartnews/onsite/MergedKSortedArrays.java new file mode 100644 index 0000000000..620c18335a --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/MergedKSortedArrays.java @@ -0,0 +1,86 @@ +package com.company.smartnews.onsite; + +import static org.junit.Assert.assertArrayEquals; + +import java.util.Comparator; +import java.util.PriorityQueue; + +/** + * LaiCode 133. Merge K Sorted Array Medium Merge K sorted array into one big sorted array in + * ascending order. + * + *

Assumptions + * + *

The input arrayOfArrays is not null, none of the arrays is null either. + */ +public class MergedKSortedArrays { + + public static void main(String[] args) { + MergedKSortedArrays sol = new MergedKSortedArrays(); + + int[][] test1 = new int[][]{{}, {1, 5, 7}, {4}, {2, 3, 5, 11}, {2, 4, 4, 6, 8}}; + int[] expected1 = new int[]{1, 2, 2, 3, 4, 4, 4, 5, 5, 6, 7, 8, 11}; + assertArrayEquals(sol.merge(test1), expected1); + + int[][] test2 = new int[][]{{1, 1, 1}, {2, 2, 2}, {3, 3, 3}, {1, 2, 3}}; + int[] expected2 = new int[]{1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3}; + assertArrayEquals(sol.merge(test2), expected2); + } + + public int[] merge(int[][] arrayOfArrays) { + // Write your solution here + // Assumptions: arrayOfArrays is not + PriorityQueue minHeap = new PriorityQueue(11, new MyComparator()); + int length = 0; + for (int i = 0; i < arrayOfArrays.length; i++) { + int[] array = arrayOfArrays[i]; + length += array.length; + if (array.length != 0) { + // We use two index to record the position of each element: + // the index of the array in the arrayOfArrays, + // the index of the element in the array. + minHeap.offer(new Entry(i, 0, array[0])); + } + } + int[] result = new int[length]; + int cur = 0; + while (!minHeap.isEmpty()) { + Entry tmp = minHeap.poll(); + result[cur++] = tmp.value; + if (tmp.y + 1 < arrayOfArrays[tmp.x].length) { + // reuse the same entry object but advance the index by 1. + tmp.y++; + tmp.value = arrayOfArrays[tmp.x][tmp.y]; + minHeap.offer(tmp); + } + } + return result; + } + + static class MyComparator implements Comparator { + + @Override + public int compare(Entry e1, Entry e2) { + if (e1.value == e2.value) { + return 0; + } + return e1.value < e2.value ? -1 : 1; + } + } + + static class Entry { + + // the row number + int x; + // the column number + int y; + // the corresponding value + int value; + + Entry(int x, int y, int value) { + this.x = x; + this.y = y; + this.value = value; + } + } +} diff --git a/src/main/java/com/company/smartnews/onsite/MinSizeSubarraySum.java b/src/main/java/com/company/smartnews/onsite/MinSizeSubarraySum.java new file mode 100644 index 0000000000..0686de919a --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/MinSizeSubarraySum.java @@ -0,0 +1,63 @@ +package com.company.smartnews.onsite; + +import static org.junit.Assert.assertEquals; + +public class MinSizeSubarraySum { + + /** + * LeetCode 209: Minimum Size Subarray Sum + * C: + *

What is the value range of the element in the array? Is negative number allow?

+ *

What is sum range of the array?

+ *

+ * A: + *

We can assume that the sum range of the array is less than Integer.MAX_VALUE

+ *

The element is always positive in the array, all element is integer

+ *

If the input array is null, empty, or target not found, return -1

+ * R: + *

1. Use two pointer start and end initially points at the beginning of the array

+ *

2.1 The semantics of start pointer: the left side of start pointer is the element we have + * processed and left behind + *

2.2 The semantics of end pointer: the left side (include the pointer) of end pointer is the + * elements that we can keep in the subarray whose sum is >= target, + * the right side fo the end pointer are the elements we are about to process

+ *

3.1 When the sum of subarray between start and end is less than target, expand the subarray + * by moving end pointer until we found the sum >= target + *

3.2 When we found the sum >= target, record and update the min size, update the sum by + * reducing what start pointer points, move the start pointer to shorten the subarray, until the + * sum is < target

+ *

3.3 keep doing 3.1 and 3.2 until end == length of nums

+ * T: + *

null, empty -> -1

+ *

[1,2], t = 7 -> -1

+ *

[2,1,3,2,7] t = 7 -> 1

+ *

[2,1,3,2] t = 5 -> 2

+ */ + + public static int minSize(int[] nums, int target) { + if (nums == null || nums.length == 0 || target <= 0) { + return -1; + } + int res = Integer.MAX_VALUE; + int sum = 0; + int start = 0; + for (int end = 0; end < nums.length; end++) { + sum += nums[end]; + while (sum >= target && start <= end) { + res = Math.min(res, end - start + 1); + sum -= nums[start++]; + } + } + return res == Integer.MAX_VALUE ? -1 : res; + } + + public static void main(String[] args) { + assertEquals(-1, minSize(null, 7)); + assertEquals(-1, minSize(new int[]{}, 7)); + assertEquals(-1, minSize(new int[]{1, 2}, 7)); + assertEquals(1, minSize(new int[]{2, 1, 3, 2, 7}, 7)); + assertEquals(2, minSize(new int[]{2, 1, 3, 2}, 5)); + + } + +} diff --git a/src/main/java/com/company/smartnews/onsite/ShuffleArrays.java b/src/main/java/com/company/smartnews/onsite/ShuffleArrays.java new file mode 100644 index 0000000000..fed28734fa --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/ShuffleArrays.java @@ -0,0 +1,5 @@ +package com.company.smartnews.onsite; + +public class ShuffleArrays { + +} diff --git a/src/main/java/com/company/smartnews/onsite/TriangleNumber.java b/src/main/java/com/company/smartnews/onsite/TriangleNumber.java new file mode 100644 index 0000000000..9febf44e36 --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/TriangleNumber.java @@ -0,0 +1,172 @@ +package com.company.smartnews.onsite; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** + * Leetcode 611. Valid Triangle Number Medium + * + *

Share Given an array consists of non-negative integers, your task is to count the number of + * triplets chosen from the array that can make triangles if we take them as side lengths of a + * triangle. + * + *

Example 1: + * + *

Input: [2,2,3,4] + * + *

Output: 3 + * + *

Explanation: + * + *

Valid combinations are: + * + *

2,3,4 (using the first 2) + * + *

2,3,4 (using the second 2) + * + *

2,2,3 + */ +public class TriangleNumber { + + // O(n^2) + public int triangleNumber(int[] nums) { + if (nums.length < 3) { + return 0; + } + int n = nums.length; + Arrays.sort(nums); // nlogn + int ans = 0; + /* + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans += 2 - 0, ans = 2 + >>>>>>>>>>>>>>>>>>>>>> + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans remains 2 + >>>>>>>>>>>>>>>>>>>>>> + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans remains 2 + >>>>>>>>>>>>>>>>>>>>> + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans += 1, ans = 3 + >>>>>>>>>>>>>>>>>>>>> + */ +// Set> results = new HashSet<>(); + for (int c = n - 1; c > 1; c--) { // n iteration + int b = c - 1; + int a = 0; + while (a < b) { // n iteration + if (nums[a] + nums[b] > nums[c]) { + ans += b - a; +// collect(results, nums, a, b, c); + b--; + } else { + a++; + } + } + } +// System.out.println(results.toString()); + return ans; + } + + private void collect(Set> results, int[] nums, int a, int b, int c) { + for (int i = a; i < b; i++) { + List result = new ArrayList<>(); + result.add(nums[a]); + result.add(nums[b]); + result.add(nums[c]); + results.add(result); + } + } + + public static void main(String[] args) { + TriangleNumber sol = new TriangleNumber(); + int[] test1 = new int[]{2, 2, 3, 4}; + int[] test2 = + new int[]{ + 15, 44, 16, 43, 47, 47, 45, 27, 46, 2, 28, 12, 49, 22, 36, 12, 6, 48, 28, 19, 18, 34, + 46, + 38, 42, 3, 21, 3, 54, 35, 21, 54, 13, 46, 50, 23, 53, 43, 5, 48, 40, 48, 10, 31, 15, 35, + 50, 8, 48, 55, 52, 18, 54, 16, 35, 4, 43, 55, 34, 13, 5, 13, 27, 41, 19, 22, 21, 26, 48, + 4, 15, 1, 45, 51, 13, 49, 22, 33, 18, 18, 52, 27, 6, 41, 7, 11, 48, 17, 37, 31, 42, 3, + 45, + 22, 6, 45, 42, 5, 28, 39, 35, 30, 24, 21, 49, 49, 47, 54, 28, 42, 40, 26, 47, 8, 28, 1, + 44, 4, 45, 23, 49, 53, 12, 48, 16, 27, 36, 21, 18, 41, 43, 9, 55, 27, 37, 41, 5, 43, 12, + 45, 0, 34, 19, 48, 14, 22, 43, 14, 13, 38, 15, 7, 41, 8, 37, 13, 45, 31, 47, 38, 45, 38, + 50, 44, 20, 40, 39, 38, 26, 29, 24, 10, 30, 23, 53, 38, 39, 3, 37, 4, 15, 22, 29, 4, 5, + 4, + 4, 19, 35, 30, 30, 49, 16, 32, 36, 26, 37, 53, 46, 28, 24, 13, 12, 29, 2, 36, 21, 19, + 15, + 11, 22, 10, 30, 29, 40, 14, 17, 39, 36, 17, 23, 39, 13, 29, 51, 8, 55, 10, 10, 47, 39, + 1, + 46, 27, 18, 7, 49, 38, 27, 14, 26, 35, 5, 46, 54, 12, 18, 30, 11, 6, 29, 52, 44, 38, 51, + 22, 26, 24, 41, 13, 39, 27, 0, 36, 38, 7, 37, 7, 9, 25, 4, 8, 52, 33, 46, 33, 42, 43, + 17, + 23, 20, 23, 41, 8, 47, 16, 48, 46, 35, 35, 24, 0, 17, 12, 40, 52, 11, 16, 7, 33, 6, 21, + 30, 32, 55, 52, 52, 28, 11, 35, 39, 15, 27, 47, 52, 0, 11, 41, 50, 10, 13, 10, 5, 40, + 21, + 0, 27, 12, 39, 20, 27, 39, 19, 28, 5, 51, 45, 19, 3, 1, 15, 53, 31, 45, 36, 33, 22, 4, + 22, + 20, 30, 7, 54, 13, 19, 48, 32, 13, 38, 9, 4, 22, 26, 22, 43, 5, 47, 14, 15, 21, 15, 48, + 10, 15, 47, 22, 9, 52, 4, 16, 22, 47, 9, 13, 44, 15, 5, 19, 2, 55, 36, 49, 25, 52, 21, + 5, + 19, 46, 2, 51, 45, 12, 54, 47, 47, 23, 17, 26, 52, 36, 49, 4, 42, 18, 20, 22, 47, 18, + 37, + 28, 19, 11, 21, 13, 37, 51, 2, 43, 36, 43, 0, 40, 50, 27, 40, 41, 31, 41, 53, 2, 17, 4, + 35, 52, 22, 25, 21, 16, 5, 41, 54, 5, 40, 3, 38, 12, 10, 53, 48, 28, 9, 7, 46, 28, 3, 9, + 44, 29, 39, 3, 41, 15, 29, 30, 47, 21, 12, 27, 53, 7, 34, 53, 53, 50, 53, 23, 46, 52, + 40, + 21, 3, 46, 49, 17, 14, 36, 10, 54, 51, 22, 25, 34, 49, 49, 26, 45, 45, 17, 30, 19, 6, + 49, + 41, 9, 19, 25, 51, 23, 55, 11, 0, 1, 13, 26, 15, 41, 38, 19, 51, 21, 11, 8, 55, 25, 21, + 15, 18, 15, 48, 4, 37, 36, 5, 45, 13, 13, 16, 26, 0, 41, 8, 51, 20, 38, 28, 46, 3, 37, + 52, + 6, 24, 11, 18, 39, 25, 48, 16, 41, 50, 44, 48, 7, 29, 14, 15, 28, 7, 46, 15, 16, 46, 20, + 35, 6, 27, 10, 17, 1, 42, 30, 37, 41, 37, 52, 55, 4, 6, 17, 27, 33, 45, 37, 11, 29, 16, + 42, 33, 39, 35, 33, 30, 25, 37, 6, 25, 22, 43, 31, 42, 25, 15, 27, 19, 15, 10, 1, 45, + 24, + 23, 17, 17, 33, 12, 53, 30, 44, 30, 2, 30, 8, 45, 49, 48, 46, 52, 13, 41, 29, 46, 39, + 50, + 51, 19, 55, 36, 29, 23, 8, 11, 49, 43, 45, 51, 2, 41, 53, 6, 38, 52, 26, 45, 0, 55, 14, + 42, 25, 10, 4, 39, 5, 47, 42, 55, 37, 35, 53, 14, 27, 54, 41, 19, 34, 38, 43, 22, 41, + 23, + 12, 13, 17, 36, 23, 41, 15, 34, 24, 44, 21, 3, 25, 10, 14, 43, 16, 35, 45, 1, 22, 26, + 20, + 5, 8, 37, 42, 47, 1, 2, 33, 2, 21, 8, 36, 50, 6, 45, 40, 48, 16, 12, 1, 55, 0, 53, 51, + 35, + 19, 14, 3, 21, 33, 2, 54, 33, 2, 18, 53, 34, 19, 23, 32, 27, 39, 13, 48, 27, 12, 7, 50, + 16, 49, 35, 27, 12, 29, 6, 34, 7, 18, 50, 6, 49, 24, 1, 18, 53, 27, 36, 0, 37, 42, 51, + 12, + 38, 8, 29, 38, 11, 24, 4, 2, 15, 19, 1, 25, 9, 30, 50, 30, 8, 15, 50, 52, 25, 8, 29, 44, + 7, 41, 30, 45, 9, 23, 20, 49, 15, 16, 48, 34, 10, 44, 52, 22, 4, 6, 2, 8, 23, 13, 39, 7, + 31, 29, 4, 35, 43, 2, 33, 34, 24, 41, 38, 47, 5, 38, 28, 34, 1, 44, 14, 13, 12, 8, 6, 0, + 24, 9, 4, 39, 37, 32, 18, 38, 15, 29, 14, 11, 40, 34, 12, 16, 7, 7, 50, 18, 24, 30, 15, + 13, 41, 42, 47, 22, 17, 14, 38, 46, 45, 22, 12, 12, 12, 25, 11, 24, 41, 8, 51, 51, 25, + 46, + 15, 13, 47, 38, 20, 0, 21, 7, 30, 49, 42, 43, 53, 24, 19, 17, 46, 50, 15, 33, 1, 42, 14, + 55, 26, 17, 41, 39, 23, 46, 35, 39, 16, 16, 37, 50, 38, 24, 20, 32, 51, 22, 53, 50, 10, + 39, 4, 2, 27, 1, 25, 18, 40, 50, 9, 35, 37, 27, 37, 39, 29, 2, 38, 32, 6, 30, 32, 4, 43, + 46, 21, 9, 40, 45, 49, 34, 37, 4, 55, 19, 47, 3, 42, 33, 13, 43, 3, 3, 22, 49 + }; + long startTime = System.currentTimeMillis(); + System.out.println(sol.triangleNumber(test2)); + System.out.println("Used time: " + (System.currentTimeMillis() - startTime)); + } +} diff --git a/src/main/java/com/company/smartnews/onsite/TriangleNumberII.java b/src/main/java/com/company/smartnews/onsite/TriangleNumberII.java new file mode 100644 index 0000000000..7b9579dcbd --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/TriangleNumberII.java @@ -0,0 +1,156 @@ +package com.company.smartnews.onsite; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Leetcode 611. Valid Triangle Number + * + *

Follow up: collect all unique triangle numbers + */ +public class TriangleNumberII { + + public Set> triangleNumber(int[] nums) { + Set> results = new HashSet<>(); + if (nums.length < 3) { + return results; + } + int n = nums.length; + Arrays.sort(nums); + /* + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans += 2 - 0, ans = 2 + >>>>>>>>>>>>>>>>>>>>>> + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans remains 2 + >>>>>>>>>>>>>>>>>>>>>> + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans remains 2 + >>>>>>>>>>>>>>>>>>>>> + i 0 1 2 3 + nums 2 2 3 4 + c + b + a + ans += 1, ans = 3 + >>>>>>>>>>>>>>>>>>>>> + */ + + for (int c = n - 1; c > 1; c--) { // n iteration + int b = c - 1; + int a = 0; + while (a < b) { // n iteration + if (nums[a] + nums[b] > nums[c]) { + // ans += b - a; + collect(results, nums, a, b, c); + b--; + } else { + a++; + } + } + } + return results; + } + + private void collect(Set> results, int[] nums, int a, int b, int c) { + for (int i = a; i < b; i++) { + List result = new ArrayList<>(); + result.add(nums[a]); + result.add(nums[b]); + result.add(nums[c]); + results.add(result); + } + } + + public static void main(String[] args) { + TriangleNumberII sol = new TriangleNumberII(); + int[] test1 = new int[]{2, 2, 3, 4}; + int[] test2 = + new int[]{ + 15, 44, 16, 43, 47, 47, 45, 27, 46, 2, 28, 12, 49, 22, 36, 12, 6, 48, 28, 19, 18, 34, + 46, + 38, 42, 3, 21, 3, 54, 35, 21, 54, 13, 46, 50, 23, 53, 43, 5, 48, 40, 48, 10, 31, 15, 35, + 50, 8, 48, 55, 52, 18, 54, 16, 35, 4, 43, 55, 34, 13, 5, 13, 27, 41, 19, 22, 21, 26, 48, + 4, 15, 1, 45, 51, 13, 49, 22, 33, 18, 18, 52, 27, 6, 41, 7, 11, 48, 17, 37, 31, 42, 3, + 45, + 22, 6, 45, 42, 5, 28, 39, 35, 30, 24, 21, 49, 49, 47, 54, 28, 42, 40, 26, 47, 8, 28, 1, + 44, 4, 45, 23, 49, 53, 12, 48, 16, 27, 36, 21, 18, 41, 43, 9, 55, 27, 37, 41, 5, 43, 12, + 45, 0, 34, 19, 48, 14, 22, 43, 14, 13, 38, 15, 7, 41, 8, 37, 13, 45, 31, 47, 38, 45, 38, + 50, 44, 20, 40, 39, 38, 26, 29, 24, 10, 30, 23, 53, 38, 39, 3, 37, 4, 15, 22, 29, 4, 5, + 4, + 4, 19, 35, 30, 30, 49, 16, 32, 36, 26, 37, 53, 46, 28, 24, 13, 12, 29, 2, 36, 21, 19, + 15, + 11, 22, 10, 30, 29, 40, 14, 17, 39, 36, 17, 23, 39, 13, 29, 51, 8, 55, 10, 10, 47, 39, + 1, + 46, 27, 18, 7, 49, 38, 27, 14, 26, 35, 5, 46, 54, 12, 18, 30, 11, 6, 29, 52, 44, 38, 51, + 22, 26, 24, 41, 13, 39, 27, 0, 36, 38, 7, 37, 7, 9, 25, 4, 8, 52, 33, 46, 33, 42, 43, + 17, + 23, 20, 23, 41, 8, 47, 16, 48, 46, 35, 35, 24, 0, 17, 12, 40, 52, 11, 16, 7, 33, 6, 21, + 30, 32, 55, 52, 52, 28, 11, 35, 39, 15, 27, 47, 52, 0, 11, 41, 50, 10, 13, 10, 5, 40, + 21, + 0, 27, 12, 39, 20, 27, 39, 19, 28, 5, 51, 45, 19, 3, 1, 15, 53, 31, 45, 36, 33, 22, 4, + 22, + 20, 30, 7, 54, 13, 19, 48, 32, 13, 38, 9, 4, 22, 26, 22, 43, 5, 47, 14, 15, 21, 15, 48, + 10, 15, 47, 22, 9, 52, 4, 16, 22, 47, 9, 13, 44, 15, 5, 19, 2, 55, 36, 49, 25, 52, 21, + 5, + 19, 46, 2, 51, 45, 12, 54, 47, 47, 23, 17, 26, 52, 36, 49, 4, 42, 18, 20, 22, 47, 18, + 37, + 28, 19, 11, 21, 13, 37, 51, 2, 43, 36, 43, 0, 40, 50, 27, 40, 41, 31, 41, 53, 2, 17, 4, + 35, 52, 22, 25, 21, 16, 5, 41, 54, 5, 40, 3, 38, 12, 10, 53, 48, 28, 9, 7, 46, 28, 3, 9, + 44, 29, 39, 3, 41, 15, 29, 30, 47, 21, 12, 27, 53, 7, 34, 53, 53, 50, 53, 23, 46, 52, + 40, + 21, 3, 46, 49, 17, 14, 36, 10, 54, 51, 22, 25, 34, 49, 49, 26, 45, 45, 17, 30, 19, 6, + 49, + 41, 9, 19, 25, 51, 23, 55, 11, 0, 1, 13, 26, 15, 41, 38, 19, 51, 21, 11, 8, 55, 25, 21, + 15, 18, 15, 48, 4, 37, 36, 5, 45, 13, 13, 16, 26, 0, 41, 8, 51, 20, 38, 28, 46, 3, 37, + 52, + 6, 24, 11, 18, 39, 25, 48, 16, 41, 50, 44, 48, 7, 29, 14, 15, 28, 7, 46, 15, 16, 46, 20, + 35, 6, 27, 10, 17, 1, 42, 30, 37, 41, 37, 52, 55, 4, 6, 17, 27, 33, 45, 37, 11, 29, 16, + 42, 33, 39, 35, 33, 30, 25, 37, 6, 25, 22, 43, 31, 42, 25, 15, 27, 19, 15, 10, 1, 45, + 24, + 23, 17, 17, 33, 12, 53, 30, 44, 30, 2, 30, 8, 45, 49, 48, 46, 52, 13, 41, 29, 46, 39, + 50, + 51, 19, 55, 36, 29, 23, 8, 11, 49, 43, 45, 51, 2, 41, 53, 6, 38, 52, 26, 45, 0, 55, 14, + 42, 25, 10, 4, 39, 5, 47, 42, 55, 37, 35, 53, 14, 27, 54, 41, 19, 34, 38, 43, 22, 41, + 23, + 12, 13, 17, 36, 23, 41, 15, 34, 24, 44, 21, 3, 25, 10, 14, 43, 16, 35, 45, 1, 22, 26, + 20, + 5, 8, 37, 42, 47, 1, 2, 33, 2, 21, 8, 36, 50, 6, 45, 40, 48, 16, 12, 1, 55, 0, 53, 51, + 35, + 19, 14, 3, 21, 33, 2, 54, 33, 2, 18, 53, 34, 19, 23, 32, 27, 39, 13, 48, 27, 12, 7, 50, + 16, 49, 35, 27, 12, 29, 6, 34, 7, 18, 50, 6, 49, 24, 1, 18, 53, 27, 36, 0, 37, 42, 51, + 12, + 38, 8, 29, 38, 11, 24, 4, 2, 15, 19, 1, 25, 9, 30, 50, 30, 8, 15, 50, 52, 25, 8, 29, 44, + 7, 41, 30, 45, 9, 23, 20, 49, 15, 16, 48, 34, 10, 44, 52, 22, 4, 6, 2, 8, 23, 13, 39, 7, + 31, 29, 4, 35, 43, 2, 33, 34, 24, 41, 38, 47, 5, 38, 28, 34, 1, 44, 14, 13, 12, 8, 6, 0, + 24, 9, 4, 39, 37, 32, 18, 38, 15, 29, 14, 11, 40, 34, 12, 16, 7, 7, 50, 18, 24, 30, 15, + 13, 41, 42, 47, 22, 17, 14, 38, 46, 45, 22, 12, 12, 12, 25, 11, 24, 41, 8, 51, 51, 25, + 46, + 15, 13, 47, 38, 20, 0, 21, 7, 30, 49, 42, 43, 53, 24, 19, 17, 46, 50, 15, 33, 1, 42, 14, + 55, 26, 17, 41, 39, 23, 46, 35, 39, 16, 16, 37, 50, 38, 24, 20, 32, 51, 22, 53, 50, 10, + 39, 4, 2, 27, 1, 25, 18, 40, 50, 9, 35, 37, 27, 37, 39, 29, 2, 38, 32, 6, 30, 32, 4, 43, + 46, 21, 9, 40, 45, 49, 34, 37, 4, 55, 19, 47, 3, 42, 33, 13, 43, 3, 3, 22, 49 + }; + long startTime1 = System.currentTimeMillis(); + System.out.println(sol.triangleNumber(test1)); + System.out.println("Test 1 used time: " + (System.currentTimeMillis() - startTime1)); + long startTime2 = System.currentTimeMillis(); + System.out.println(sol.triangleNumber(test2)); + System.out.println("Test 2 used time: " + (System.currentTimeMillis() - startTime2)); + } +} diff --git a/src/main/java/com/company/smartnews/onsite/ValidStackSequence.java b/src/main/java/com/company/smartnews/onsite/ValidStackSequence.java new file mode 100644 index 0000000000..cb49644cd7 --- /dev/null +++ b/src/main/java/com/company/smartnews/onsite/ValidStackSequence.java @@ -0,0 +1,69 @@ +package com.company.smartnews.onsite; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertFalse; + +import java.util.ArrayDeque; +import java.util.Deque; + +public class ValidStackSequence { + + /** + * LeetCode 946: Valid Stack Sequence + * + * C: + *

What is the data type of input and output? array and boolean?

+ *

What if we meet a null as input?

+ *

Can we assume the length of popped and pushed are the same? And how long they can be?

+ *

What is the value range if the element in the sequences

+ * A: + *

The input can be null, thus return false

+ *

The length of popped and pushed sequences can be different, if popped is longer than pushed, + * return false

+ *

No duplicate element in the sequences

+ * R: + *

Use a stack to simulate the pushed and popped sequence. + *

Use a pointer popCount points at the head of popped sequence initially, the semantic of the + * pointer is : the left side of the pointer is the valid popped sequence we have been checked. + *

+ *

if the pop count is equal to the length of popped sequence, the popped sequence is + * valid

+ * T: + *

pushed:1,2,3, popped: 1,2,3 => true, 3,2,1=> true, 3,1,2 => false, null => false,

+ */ + public static boolean isValidStachSequence(int[] pushed, int[] popped) { + if (pushed == null || popped == null || pushed.length < popped.length) { + return false; + } + Deque stack = new ArrayDeque<>(); + int popCount = 0; + for (int i = 0; i < pushed.length; i++) { + stack.addLast(pushed[i]); + while (!stack.isEmpty() && popCount < popped.length && stack.peekLast() == popped[popCount]) { + stack.pollLast(); + popCount++; + } + } + return popCount == popped.length; + } + + public static void main(String[] args) { + int[] pushed1 = new int[]{1, 2, 3}; + int[] pushed2 = new int[]{1, 2, 3, 4, 5, 6}; + int[] popped1 = new int[]{1, 2, 3}; + int[] popped2 = new int[]{3, 2, 1}; + int[] popped3 = null; + int[] popped4 = new int[]{1, 2, 3, 4, 5, 6, 7, 8}; + int[] popped5 = new int[]{3, 1, 2}; + + assertTrue(isValidStachSequence(pushed1, popped1)); + assertTrue(isValidStachSequence(pushed1, popped2)); + assertTrue(isValidStachSequence(pushed2, popped1)); + assertTrue(isValidStachSequence(pushed2, popped2)); + + assertFalse(isValidStachSequence(pushed1, popped3)); + assertFalse(isValidStachSequence(pushed1, popped5)); + assertFalse(isValidStachSequence(pushed1, popped4)); + + } +} diff --git a/src/main/java/com/company/snapchat/phone/tree/BinaryTreePostOrderIterator.java b/src/main/java/com/company/snapchat/phone/tree/BinaryTreePostOrderIterator.java new file mode 100644 index 0000000000..4c0b717a41 --- /dev/null +++ b/src/main/java/com/company/snapchat/phone/tree/BinaryTreePostOrderIterator.java @@ -0,0 +1,74 @@ +package com.company.snapchat.phone.tree; + +import com.fishercoder.common.classes.TreeNode; +import com.fishercoder.common.utils.TreeUtils; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; + +public class BinaryTreePostOrderIterator { + + private Deque stack = new ArrayDeque<>(); + private LinkedList out = new LinkedList<>(); + + // 1. Post-order is the reverse order of pre-order with traversing right substree before traversing + // left subtree: + // pre-order : root -> left-subtree -> right-subtree + // pre-order-visit-right-first: root -> right-subtree -> left-subtree + // reversed-(pre-order-visit-right-first): left-subtree -> right-subtree -> root + // post-order: left-subtree -> right-subtree -> root + // + // 2. And since stack is LIFO, we should push left substree to stack, then right substree. + // 3. So for next step, the top element of stack is right subtree. + // 4. And we need to also reverse the order of the elements poped from stack. + // 5. So we use another linkedList based stack to maintain the reverse order + public BinaryTreePostOrderIterator(TreeNode root) { + stack.addFirst(root); + while (!stack.isEmpty()) { + TreeNode node = stack.removeFirst(); + out.addFirst(node); + if (node.left != null) { + stack.addFirst(node.left); + } + if (node.right != null) { + stack.addFirst(node.right); + } + } + } + + public boolean hasNext() { + return !out.isEmpty(); + } + + public TreeNode next() { + if (!hasNext()) { + return null; + } + return out.removeFirst(); + } + + public static void main(String[] args) { + + List list = Arrays.asList(new Integer[] {5, 3, 6, 2, 4, null, null, 1}); + /** + * the tree for [5, 3, 6, 2, 4, null, null, 1], i.e. looks like the following: + 5 + / \ + 3 6 + / \ / \ + 2 4 # # + / + 1 + */ + TreeNode root = TreeUtils.constructBinaryTree(list); + List result = new ArrayList<>(); + BinaryTreePostOrderIterator iterator = new BinaryTreePostOrderIterator(root); + while (iterator.hasNext()) { + result.add(iterator.next().val); + } + System.out.println(result.toString()); // [1, 2, 4, 3, 6, 5] + } +} diff --git a/src/main/java/com/company/vmware/decodestr/DecodeAsciiString.java b/src/main/java/com/company/vmware/decodestr/DecodeAsciiString.java new file mode 100644 index 0000000000..45779444f3 --- /dev/null +++ b/src/main/java/com/company/vmware/decodestr/DecodeAsciiString.java @@ -0,0 +1,89 @@ +package com.company.vmware.decodestr; + +import java.util.ArrayList; +import java.util.List; + +/** + * We encode a string, s, by performing the following sequence of actions: + * + *

Replace each character with its ASCII value representation. Reverse the string. For example, + * the table below shows the conversion from the string "Go VMWare" to the ASCII string + * "711113286778797114101": + * + *

Character G o V M W a r e ASCII Value 71 111 32 86 77 87 97 114 101 + * + *

We then reverse the ASCII string to get the encoded string 101411797877682311117. For + * reference, the characters in s are ASCII characters within the range 10 - 126 which include + * special characters. The function must decode the encoded string and return the list of ways in + * which s can be decoded. + * + *

// encoded - A reversed ASCII string denoting an encoded string s static Collection + * decode(String encoded) { + * + *

return Collection } + */ +public class DecodeAsciiString { + public static List decode(String encoded) { + List ans = new ArrayList<>(); + + StringBuilder input1 = new StringBuilder(); + + // append a string into StringBuilder input1 + input1.append(encoded); + + // reverse StringBuilder input1 + input1 = input1.reverse(); + + // print reversed String + // System.out.println(input1); + + char[] encodedArr = encoded.toCharArray(); + + decodeHelper(0, encodedArr.length, new StringBuilder(), ans, input1.toString()); + + for (String s : ans) { + System.out.println(s); + } + return ans; + } + + public static void decodeHelper( + int start, int length, StringBuilder sb, List ans, String encoded) { + + if (start >= length - 1) { + ans.add(sb.toString()); + return; + } + List splitList = new ArrayList<>(); + if (start + 2 <= length) { + // get the first 2 chars of the string + splitList.add(encoded.substring(start, start + 2)); + } + if (start + 3 <= length) { + // get the first 3 chars of the string + splitList.add(encoded.substring(start, start + 3)); + } + // For each substring in splitList, check if it is valid ASCII value, + for (String each : splitList) { + if (isValid(each)) { + // System.out.println(each); + sb.append((char) (Integer.parseInt(each))); + decodeHelper(start + each.length(), length, sb, ans, encoded); + sb.setLength(sb.length() - 1); // back tracking + } + } + } + + public static boolean isValid(String s) { + int val = Integer.parseInt(s); + return (val >= 10 && val <= 126); + } + + public static void main(String[] args) { + System.out.println("Hello World!"); + // String ss = "0018014111117811180180110127"; + // decode(ss); + // decode("64101301011794019923111611236112117900179231116112312161150180150189792310140161123511501231019901110130150180180110161101137"); + decode("101411797877682311117"); + } +} diff --git a/src/main/java/com/company/vmware/finddup/FindDupInFileSystem.java b/src/main/java/com/company/vmware/finddup/FindDupInFileSystem.java new file mode 100644 index 0000000000..a90d48eae5 --- /dev/null +++ b/src/main/java/com/company/vmware/finddup/FindDupInFileSystem.java @@ -0,0 +1,47 @@ +package com.company.vmware.finddup; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Leetcode 609. Find Duplicate File in System */ +class FindDupInFileSystem { + // High level: + // 1. split the string into: pair of + // 2. use content as key, group all the pair into a hashmap: Map> + // 3. add the values of above hash map entries to a List> result + public List> findDuplicate(String[] paths) { + List> result = new ArrayList<>(); + if (paths == null | paths.length == 0) { + return result; + } + Map> map = new HashMap<>(); + + for (String folder : paths) { + String[] folderSubstr = folder.split(" "); + mapAndGroup(map, folderSubstr); + } + map.entrySet().stream() + .filter(e -> (e.getValue() != null && e.getValue().size() > 1)) + .forEach( + e -> { + result.add(e.getValue()); + }); + return result; + } + + private void mapAndGroup(Map> map, String[] s) { + String dir = s[0]; + for (int i = 1; i < s.length; i++) { + String[] metaData = s[i].split("\\("); + String fileName = metaData[0]; + String content = metaData[1].substring(0, metaData[1].length() - 1); + String file = dir + "/" + fileName; + if (!map.containsKey(content)) { + map.put(content, new ArrayList<>()); + } + map.get(content).add(file); + } + } +} diff --git a/src/main/java/com/company/vmware/hangman/HangmanSolver.java b/src/main/java/com/company/vmware/hangman/HangmanSolver.java new file mode 100644 index 0000000000..d634c8dfb9 --- /dev/null +++ b/src/main/java/com/company/vmware/hangman/HangmanSolver.java @@ -0,0 +1,75 @@ +package com.company.vmware.hangman; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Design data structure for HangMan solver game. We are given array of lexocographically sorted + * strings 'dict[]' as input and a pattern 'puzzle', return list of all the words matching pattern + * 'puzzle'. 'puzzle' is a pattern containing underscore character "_". + * + *

class HangmanSolver { + * + *

public HangmanSolver(String[] dict) { // todo } + * + *

public List solve(String puzzle) { // todo } } Here solve method could be called + * multiple times however HangManSolver() will be called only once. So the problem is to process + * strings in the input array and store in a data structure efficient for searching strings matching + * given pattern. + * + *

Example: + * + *

HangmanSolver solver = new HangmanSolver(["ant", "feet", "meet", "zebra"]); + * solver.solve("_e_t"); // ["feet", "meet"] + */ +public class HangmanSolver { + + private HangmanTrieNode root; + + public HangmanSolver(List dict) { + root = new HangmanTrieNode(' '); + for (String word : dict) { + HangmanTrieNode ref = root; + for (char c : word.toCharArray()) { + ref.next[c - 'a'] = new HangmanTrieNode(c); + ref = ref.next[c - 'a']; + } + ref.word = word; + } + } + + public List solve(String puzzle) { + List result = new ArrayList<>(); + dfs(root, result, puzzle, 0); + return result; + } + + private void dfs(HangmanTrieNode root, List result, String puzzle, int cur) { + // base case: no such char root in the dictionary + if (root == null || cur > puzzle.length()) { + return; + } + if (cur == puzzle.length()) { + if (root.word != null) { + result.add(root.word); + } + return; + } + + char pChar = puzzle.charAt(cur); + if (pChar == '_') { + for (HangmanTrieNode next : root.next) { + dfs(next, result, puzzle, cur + 1); + } + } else { + dfs(root.next[pChar - 'a'], result, puzzle, cur + 1); + } + } + + public static void main(String[] args) { + List dict1 = Arrays.asList(new String[] {"ant", "feet", "meet", "zebra"}); + HangmanSolver solver1 = new HangmanSolver(dict1); + System.out.println(solver1.solve("_e_t").toString()); + } +} diff --git a/src/main/java/com/company/vmware/hangman/HangmanTrieNode.java b/src/main/java/com/company/vmware/hangman/HangmanTrieNode.java new file mode 100644 index 0000000000..fdb5e5a3c7 --- /dev/null +++ b/src/main/java/com/company/vmware/hangman/HangmanTrieNode.java @@ -0,0 +1,12 @@ +package com.company.vmware.hangman; + +public class HangmanTrieNode { + char val; + HangmanTrieNode[] next; + String word; + + public HangmanTrieNode(char val) { + this.val = val; + this.next = new HangmanTrieNode[26]; + } +} diff --git a/src/main/java/com/company/vmware/json/JsonValidator.java b/src/main/java/com/company/vmware/json/JsonValidator.java new file mode 100644 index 0000000000..34b38c6ef9 --- /dev/null +++ b/src/main/java/com/company/vmware/json/JsonValidator.java @@ -0,0 +1,160 @@ +package com.company.vmware.json; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * Validate a json and return true or false. + */ +public class JsonValidator { + + public static void main(String[] args) { + String test1 = "{}"; // true + String test2 = "{"; // false + String test3 = "{\"x\" : { \"y\" : \"z\"}}"; // true + String test4 = + "{ \n" + + " \"glossary\":{ \n" + + " \"title\":\"exampleglossary\",\n" + + " \"GlossDiv\":{ \n" + + " \"title\":\"S\",\n" + + " \"GlossList\":{ \n" + + " \"GlossEntry\":{ \n" + + " \"ID\":\"SGML\",\n" + + " \"SortAs\":\"SGML\",\n" + + " \"GlossTerm\":\"StandardGeneralizedMarkupLanguage\",\n" + + " \"Acronym\":\"SGML\",\n" + + " \"Abbrev\":\"ISO8879:1986\",\n" + + " \"GlossDef\":{ \n" + + " \"para\":\"Ameta-markuplanguage,usedtocreatemarkuplanguagessuchasDocBook.\",\n" + + " \"GlossSeeAlso\":[ \n" + + " \"GML\",\n" + + " \"XML\"\n" + + " ]\n" + + " },\n" + + " \"GlossSee\":\"markup\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + String test5 = "[{\n" + "\t\"\": \"\"\n" + "}]"; + String test6 = "[\n" + "\t[]"; + // assertTrue(isValid(test1)); + // assertFalse(isValid(test2)); + // assertTrue(isValid(test3)); + assertTrue(isValid(test4)); + assertTrue(isValid(test5)); + assertFalse(isValid(test6)); + } + + public static boolean isValid(String s) { + Deque stack = new ArrayDeque<>(); + char[] chars = s.toCharArray(); + for (int i = 0; i < chars.length; i++) { + // TODO handle numeric values in json + + // if(!stack.isEmpty() && stack.peekLast() == ':') { + // if(chars[i] == '"' || chars[i] == '{' || chars[i] == '[' || + // Character.isDigit(chars[i])) { + // if(chars[i] == '"' || chars[i] == '{' || chars[i] == '['){ + // stack.addLast(chars[i]); + // } else if (Character.isDigit(chars[i])) { + // if(chars[i] == '0'){ + // stack.addLast(chars[i]); + // } + // } + // } else { + // // {"x" : a } + // System.out.println("processed: " + s.substring(0, i)); + // System.out.println("chars[i]: " + chars[i]); + // return false; + // } + // } else if(!stack.isEmpty() && stack.peekLast() == '0') { + // if(chars[i] != '.') { + // System.out.println("processed: " + s.substring(0, i)); + // System.out.println("chars[i]: " + chars[i]); + // return false; + // } else { + // stack.addLast(chars[i]); + // } + // } else if(!stack.isEmpty() && stack.peekLast() == '.') { + // if(!Character.isDigit(chars[i])) { + // return false; + // } + // } else if(isFocusSymbol(chars[i])) { + + // Handle non-numeric values + if (isFocusSymbol(chars[i])) { + if (stack.isEmpty()) { + stack.addLast(chars[i]); + } else { + // stack is not empty + char top = stack.peekLast(); + if (!isValidTop(top)) { + System.out.println("processed: " + s.substring(0, i)); + System.out.println("chars[i]: " + chars[i]); + return false; + } else { + // top can be , { [ " : + if (top == '{') { + if (chars[i] == ']') { + System.out.println("processed: " + s.substring(0, i)); + System.out.println("chars[i]: " + chars[i]); + return false; + } else if (chars[i] == '}') { + stack.removeLast(); + } else { + stack.addLast(chars[i]); + } + } else if (top == '[') { + if (chars[i] == ':' || chars[i] == '}') { + System.out.println("processed: " + s.substring(0, i)); + System.out.println("chars[i]: " + chars[i]); + return false; + } else if (chars[i] == ']') { + stack.removeLast(); + } else { + stack.addLast(chars[i]); + } + } else if (top == ':' || top == ',') { + if (chars[i] == ']' || chars[i] == '}' || chars[i] == ',' || chars[i] == ':') { + System.out.println("processed: " + s.substring(0, i)); + System.out.println("chars[i]: " + chars[i]); + return false; + } else { + // if (chars[i] == '{' || chars[i] == '[' || chars[i] == '"') + stack.removeLast(); + stack.addLast(chars[i]); + } + } else { + // if (top == '"') + if (chars[i] == '"') { + stack.removeLast(); + } else { + // skip any character inside the quotation mark + continue; + } + } + } + } + } else { + // skip literals + continue; + } + } + return stack.isEmpty(); + } + + private static boolean isFocusSymbol(char ch) { + return (ch == '{' || ch == '}' || ch == '[' || ch == ']' || ch == ':' || ch == ',' + || ch == '"'); + } + + private static boolean isValidTop(char ch) { + return (ch == '{' || ch == '[' || ch == ':' || ch == ',' || ch == '"'); + } +} diff --git a/src/main/java/com/company/vmware/myrand/MyRand.java b/src/main/java/com/company/vmware/myrand/MyRand.java new file mode 100644 index 0000000000..4067e23db6 --- /dev/null +++ b/src/main/java/com/company/vmware/myrand/MyRand.java @@ -0,0 +1,46 @@ +package com.company.vmware.myrand; + +import java.util.StringJoiner; + +public final class MyRand { + + /** + * Generate random decimal number between [5,55] inclusively with given rand_0() that randomly + * return 0 or 1; + * + * @return + */ + public static int getRand() { + + StringJoiner s = new StringJoiner(""); + while (true) { + if (s.length() < 8) { + s.add(String.valueOf(oneOrZero())); + continue; + } + + int v = Integer.parseInt(s.toString(), 2); + + if (v >= 5 && v <= 55) { + return v; + } else { + s = new StringJoiner(""); + } + } + } + + /** + * rand_0() that randomly return 0 or 1 + * + * @return + */ + private static int oneOrZero() { + return (int) Math.round(Math.random()); + } + + public static void main(String[] args) { + for (int i = 0; i < 10; i++) { + System.out.println(MyRand.getRand()); + } + } +} diff --git a/src/main/java/com/company/vmware/robot/Robot.java b/src/main/java/com/company/vmware/robot/Robot.java new file mode 100644 index 0000000000..2d4a390a0d --- /dev/null +++ b/src/main/java/com/company/vmware/robot/Robot.java @@ -0,0 +1,170 @@ +package com.company.vmware.robot; + +import java.util.LinkedList; + +/** + * Design Robot class that can move around on a two dimensional plane. It needs to be able to change + * its position, report its position and report its last move as described below. Implement a Robot + * class per following specifications: Fields: integer currentX - The robot's current x-coordinate + * in the 2D plane integer currentY - The robot's current y-coordinate in the 2D plane integer + * previousX - The robot's x-coordinate in the 2D plane prior to its most recent movement integer + * previousY - The robot's y-coordinate in the 2D plane prior to its most recent movement **Note: ** + * The robot's initial location is at (x,y) coordinate (0,5) + * + *

Parameterized Constructor: x - The value of currentX for the new Robot y - The value of + * currentY for the new Robot + * + *

public Robot(integer x, integer y) { } The robot created by this constructor is considered to + * have spawned at(0,5) and moved to (currentX, currentY) so (previousX, previousY) starts as (0,5) + * + *

Methods: + * + *

void printCurrentCoordinates() - Print two space-separated integers describing the robot's + * current x and y coordinates. + * + *

void moveX(integer dx) - Move the robot from current position(x,y) to new position(x+dx, y). + * Remember to maintain previousX. + * + *

void moveY(integer dy) - Move the robot from current position(x,y) to new position(x, y+dy). + * Remember to maintain previousY. + * + *

void printLastCoordinates() - Print two space-separated integers describing the robot's + * previousX and previousY coordinates. This will be called after the robot has moved from position + * (0,5) at least once + * + *

void printLastMove() - Print two space-separated values describing the robot's most recent + * movement + * + *

Sample input: 2 1, 1, 2, 0 + * + *

Sample output: 0 5 , 2 1, x 1, 3 1, 3 1, x 2, 5 2, 5 2 + * + *

Explanation: The firstRobot object is initially at position (0,5), so the call to + * firstRobot.printCurrentCoordinates() prints 0 5 For the secondRobot object created with the + * parameterized constructor, it was created and moved from (0,5) -> (2,1) so + * secondRobot.printCurrentCoordinates() prints 2 1. Next, we call the following sequence of methods + * on the secondRobot object. + * + *

secondRobot.moveX(1) moves the robot 1 unit from (2,1) -> (3,1) + * + *

secondRobot.printLastMove() prints x 1 as its last movement was moveX(1) + * + *

secondRobot.printCurrentCoordinates() prints 3 1 because it moved from (2,1) ->(3,1) + * + *

secondRobot.moveY(1) moves the robot 1 unit from (3,1) -> (3,2) + * + *

secondRobot.printLastCoordinates() prints 3 1 bcause its last movement was (3,1) -> (3,2), so + * the coordinates of its last location prior to the movement was (3,1) At this point, the test code + * adds 1 to dx => dx = 2 and subtracts 1 from dy => dy = 0 + * + *

secondRobot.moveX(2) moves the robot from the (3,2) -> (5,2) + * + *

secondRobot.printLastMove() prints x 2 as its last movement was moveX(2) + * + *

secondRobot.printCurrentCoordinates() prints 5 2 because it moved from (3,2) -> (5,2) + * + *

secondRobot.moveY(0) moves the robot 0 units from (5,2) -> (5,2) + * secondRobot.printLastCoordinates() prints 5 2 because its last movment was (5,2) -> (5,2) + */ + +/** + * High level: Use 4 stacks to keep track on robot's coordinate X and Y's position history and move + * history respectively. So the above example looks like the following with 4 stacks: + * + *

X [0 2 3 3 5 5 + * + *

dX [0 2 1 0 2 0 + * + *

Y [5 1 1 2 2 2 + * + *

dY [0 -4 0 1 0 0 + */ +public class Robot { + public static int INIT_X = 0; + public static int INIT_Y = 5; + + private LinkedList xStack = + new LinkedList() { + { + add(INIT_X); + } + }; + private LinkedList dxStack = + new LinkedList() { + { + add(0); + } + }; + private LinkedList yStack = + new LinkedList() { + { + add(INIT_Y); + } + }; + private LinkedList dyStack = + new LinkedList() { + { + add(0); + } + }; + + public Robot(int x, int y) { + dxStack.addLast(x - xStack.getLast()); + xStack.addLast(x); + dyStack.addLast(y - yStack.getLast()); + yStack.addLast(y); + System.out.println("initial curr (x, y): " + xStack.getLast() + " " + yStack.getLast()); + System.out.println( + "initial last (x, y): " + + xStack.get(xStack.size() - 1 - 1) + + " " + + yStack.get(yStack.size() - 1 - 1)); + } + + public void move(int dx, int dy) { + dxStack.addLast(dx); + dyStack.addLast(dy); + xStack.addLast(xStack.getLast() + dx); + yStack.addLast(yStack.getLast() + dy); + } + + public void moveX(int dx) { + move(dx, 0); + } + + public void moveY(int dy) { + move(0, dy); + } + + public void printCurrentCoordinates() { + System.out.println("current (x, y): " + xStack.peekLast() + " " + yStack.peekLast()); + } + + public void printLastCoordinates() { + int lastX = xStack.getLast() - dxStack.getLast(); + int lastY = yStack.getLast() - dyStack.getLast(); + System.out.println("last (x, y): " + lastX + " " + lastY); + } + + public void printLastMove() { + int lastDx = dxStack.getLast(); + int lastDy = dyStack.getLast(); + System.out.println( + "last move: " + (lastDx == 0 ? "x" : lastDx) + " " + (lastDy == 0 ? "x" : lastDy)); + } + + public static void main(String[] args) { + + Robot secondRobot = new Robot(2, 1); + secondRobot.moveX(1); // (2, 1) -> (3, 1) + secondRobot.printLastMove(); // (1, x) + secondRobot.printCurrentCoordinates(); // (3,1) + secondRobot.moveY(1); // (3, 1) - > (3, 2) + secondRobot.printLastCoordinates(); // (3, 1) + secondRobot.moveX(2); // (3,2) -> (5, 2) + secondRobot.printLastMove(); // (2, x) + secondRobot.printCurrentCoordinates(); // (5, 2) + secondRobot.moveY(0); // (5, 2) -> (5, 2) + secondRobot.printLastCoordinates(); // (5, 2) + } +} diff --git a/src/main/java/com/company/yoyo/onsite/MajorityElementVariant.java b/src/main/java/com/company/yoyo/onsite/MajorityElementVariant.java new file mode 100644 index 0000000000..b27d56d6d5 --- /dev/null +++ b/src/main/java/com/company/yoyo/onsite/MajorityElementVariant.java @@ -0,0 +1,171 @@ +package com.company.yoyo.onsite; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class MajorityElementVariant { + + /** + * Leetcode 229. Majority Element II Variant Given an sorted integer array of size n, find all + * elements that appear more than ⌊ n/3 ⌋ times. + * + *

Note: The algorithm should run in linear time and in O(1) space. + * + *

Example 1: + * + *

Input: [1, 3, 3] Output: [3] + * + *

Example 2: + * + *

Input: [1, 2, 2, 3, 6, 6, 6, 7] Output: [6] + */ + public static void main(String[] args) { + int[] test1 = new int[] {1, 2, 2, 3, 6, 6, 6, 7}; + int[] test2 = new int[] {1}; + int[] test3 = new int[] {1, 2}; + int[] test4 = new int[] {1, 2, 3}; + // There are more than 33 integer '30's in the test 5 array, the length of test 5 is 100 + int[] test5 = + new int[] { + 2, 3, 4, 4, 5, 5, 9, 11, 11, 14, 14, 15, 18, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 56, 57, 58, 62, 62, 62, 63, 65, 67, 67, 68, 70, 71, 71, 71, 71, 72, 72, 74, 75, + 75, 76, 76, 78, 78, 79, 79, 79, 79, 81, 82, 83, 83, 84, 84, 86, 87, 88, 90, 91, 92, 94, + 94, 95, 95, 97, 97, 98, 99, 99, 100, 100 + }; + List tests = new ArrayList<>(); + tests.add(test1); + tests.add(test2); + tests.add(test3); + tests.add(test4); + tests.add(test5); + + int i = 1; + for (int[] testCase : tests) { + List myResult = myMajorityElement(testCase); + List expected = majorityElement(testCase); + Collections.sort(expected); + System.out.println("test " + i + " My Result: " + myResult.toString()); + System.out.println("test " + i + " Expected: " + expected.toString()); + i++; + assertEquals(expected, myResult); + } + } + + public static List majorityElement(int[] nums) { + List result = new ArrayList<>(); + if (nums == null || nums.length == 0) { + return result; + } + // At maximum we can have two elments qualified the condition + int count1 = 0; + int count2 = 0; + int candidate1 = 0; + int candidate2 = 1; + for (int num : nums) { + // System.out.println(candidate1 + " : " + count1); + // System.out.println(candidate2 + " : " + count2); + if (num == candidate1) { + count1++; + } else if (num == candidate2) { + count2++; + } else if (count1 == 0) { + candidate1 = num; + count1 = 1; + } else if (count2 == 0) { + candidate2 = num; + count2 = 1; + } else { + count1--; + count2--; + } + } + // System.out.println(candidate1 + " : " + count1); + // System.out.println(candidate2 + " : " + count2); + count1 = 0; + count2 = 0; + for (int num : nums) { + if (num == candidate1) { + count1++; + } else if (num == candidate2) { + count2++; + } + } + if (count1 > nums.length / 3) { + result.add(candidate1); + } + if (count2 > nums.length / 3) { + result.add(candidate2); + } + return result; + } + + public static List myMajorityElement(int[] nums) { + Set res = new HashSet<>(); + + if (nums == null || nums.length == 0) { + return new ArrayList<>(); + } else if (nums.length < 3) { + List shortRes = new ArrayList<>(2); + for (int num : nums) { + shortRes.add(num); + } + return shortRes; + } + + // Arrays.sort(nums); + int len = nums.length; + for (int pivot = len / 3; pivot < len; pivot += len / 3) { + int target = nums[pivot]; + int left = pivot - len / 3; + int first = findFirst(target, nums, left, pivot); + int right = (pivot + len / 3 > len - 1) ? len - 1 : pivot + len / 3; + int last = findLast(target, nums, pivot, right); + if (last - first + 1 > len / 3) { + res.add(target); + } + } + return new ArrayList<>(res); + } + + private static int findLast(int T, int[] nums, int pivot, int right) { + int l = pivot; + int r = right; + while (l + 1 < r) { + int mid = l + (r - l) / 2; + if (nums[mid] == T) { + l = mid; + } else if (nums[mid] > T) { + r = mid; + } + } + if (nums[r] == T) { + return r; + } else { + return l; + } + } + + private static int findFirst(int T, int[] nums, int left, int pivot) { + int l = left; + int r = pivot; + while (l + 1 < r) { + int mid = l + (r - l) / 2; + if (nums[mid] == T) { + r = mid; + } else if (nums[mid] < T) { + l = mid; + } + } + if (nums[l] == T) { + return l; + } else { + return r; + } + } +} diff --git a/src/main/java/com/laioffer/dfs/StringPermutationWithDupChars.java b/src/main/java/com/laioffer/dfs/StringPermutationWithDupChars.java new file mode 100644 index 0000000000..bb8adc0483 --- /dev/null +++ b/src/main/java/com/laioffer/dfs/StringPermutationWithDupChars.java @@ -0,0 +1,34 @@ +package com.laioffer.dfs; + +import java.util.ArrayList; +import java.util.List; + +/* +Assumption: (1) given input is char array ahd not null, not empty (2) output is a list of all permutation Strings +High level: use DFS to traverse all permutations. (1) N levels of recursion tree, each level represents one position. (2) at each level, we need traverse each node with remaining unused letters: i-th level, each node: (n - i) branches +Recursion tree: + root = aab + / | \ + i = 0, 1, 2 swap(0,0). swap(0,1) swap(0, 2) +position 0 **a**ab ~~**a**ab~~ **b**aa n = 3 + / \ / \ / \ + i = 1, 2 swap(1,1) swap(1,2) swap(1,1) swap(1,2) +position 1 a**a**b a**b**a ~~a**a**b a**b**a~~ b**a**a. ~~b**a**a~~ * (3-1) + | | | | | | + i = 2 swap(2,2) swap(2,2) + position 2 aa**b** ab**a** ~~aa**b** ab**a**~~ ba**a** ~~ba**a**~~ * (3 - 2) + clone each string at position 2: O(n) * O(n!) brances +Time: O(N!*N), Space(the height of the recursion tree) = O(N) +*/ +public class StringPermutationWithDupChars { + public static List findPermutations(char[] input) { + List result = new ArrayList<>(); + dfs(input, 0, result); + return result; + } + + public static void dfs(char[] input, int index, List result) { + + } +} + diff --git a/src/main/java/com/laioffer/dfs/_99Cents.java b/src/main/java/com/laioffer/dfs/_99Cents.java new file mode 100644 index 0000000000..59180aaa23 --- /dev/null +++ b/src/main/java/com/laioffer/dfs/_99Cents.java @@ -0,0 +1,93 @@ +package com.laioffer.dfs; + +import java.util.ArrayList; +import java.util.List; + +public class _99Cents { + + /** + * Given a number of different denominations of coins (e.g., 1 cent, 5 cents, 10 cents, 25 cents), + * get all the possible ways to pay a target number of cents. + * + *

Arguments + * + *

coins - an array of positive integers representing the different denominations of coins, + * there are no duplicate numbers and the numbers are sorted by descending order, eg. {25, 10, 5, + * 2, 1} target - a non-negative integer representing the target number of cents, eg. 99 + * Assumptions + * + *

coins is not null and is not empty, all the numbers in coins are positive target >= 0 You + * have infinite number of coins for each of the denominations, you can pick any number of the + * coins. Return + * + *

a list of ways of combinations of coins to sum up to be target. each way of combinations is + * represented by list of integer, the number at each index means the number of coins used for the + * denomination at corresponding index. Examples + * + *

coins = {2, 1}, target = 4, the return should be + * + *

[ + * + *

[0, 4], (4 cents can be conducted by 0 * 2 cents + 4 * 1 cents) + * + *

[1, 2], (4 cents can be conducted by 1 * 2 cents + 2 * 1 cents) + * + *

[2, 0] (4 cents can be conducted by 2 * 2 cents + 0 * 1 cents) + * + *

] + */ + public static void main(String[] args) { + int[] coin = new int[] {25, 10, 5, 1}; + findCoinCombination(coin, 99, 0, new int[4]); + List> result = combinations(99, coin); + } + + public static List> combinations(int target, int[] coins) { + List> result = new ArrayList>(); + List cur = new ArrayList(); + helper(target, coins, 0, cur, result); + return result; + } + + private static void helper( + int target, int[] coins, int index, List cur, List> result) { + if (index == coins.length - 1) { + if (target % coins[coins.length - 1] == 0) { + cur.add(target / coins[coins.length - 1]); + result.add(new ArrayList(cur)); + cur.remove(cur.size() - 1); + } + return; + } + int max = target / coins[index]; + for (int i = 0; i <= max; i++) { + cur.add(i); + helper(target - i * coins[index], coins, index + 1, cur, result); + cur.remove(cur.size() - 1); + } + } + + public static void findCoinCombination(int[] coin, int moneyLeft, int index, int[] sol) { + if (index == 3) { + sol[index] = moneyLeft; + printSol(sol, coin); + return; + } + + for (int i = 0; i <= moneyLeft / coin[index]; i++) { + sol[index] = i; + findCoinCombination(coin, moneyLeft - i * coin[index], index + 1, sol); + } + } + + private static void printSol(int[] sol, int[] coin) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < sol.length; i++) { + sb.append(sol[i]); + sb.append('x'); + sb.append(coin[i]); + sb.append(" cent "); + } + System.out.println(sb.toString()); + } +}