package leetcode.blog; import java.util.ArrayList; import java.util.Arrays; public class LeetcodeBlog { // Q1 Find Intersection of two Sorted Arrays // if either A or B 's length is too big, try to use Binary Search should be // a good idea, which is O(mlgn) // this method is O(m + n) public static ArrayList<Integer> findIntersection(int[] A, int[] B) { ArrayList<Integer> res = new ArrayList<Integer>(); if (A.length == 0 || B.length == 0) return res; for (int i = 0, j = 0; i < A.length && j < B.length;) { if (A[i] == B[j]) { res.add(A[i]); i++; j++; } else if (A[i] < B[j]) i++; else j++; } return res; } // Q2 Reverse Linked List both Iteratively and Recursively public static LinkedListNode reverseLinkedListIteratively( LinkedListNode head) { if (head == null) return head; LinkedListNode res = new LinkedListNode(0); LinkedListNode next; while (head != null) { next = head.next; head.next = res.next; res.next = head; head = next; } return res.next; } public static LinkedListNode reverseLinkedListRecursively( LinkedListNode head) { if (head == null) return head; if (head.next == null) return head; LinkedListNode newHead = reverseLinkedListRecursively(head.next); head.next.next = head; head.next = null; return newHead; } // Q3 Determine if a point is inside a rectangle/irregular polygon // Rectangle ABCD and Point P // 1. Calculate the sum of areas of all triangles. ABP, BCP, CDP, DAP. // if the sum is larger than the area of the rectangle, P is outside the // rectangle // if the sum is smaller than the area of the rectangle, P is inside the // rectangle // if equal, it is on one side line. // 2. Calculate the perpendicular distances of P from all the 4 lines // Q4 Rotating an array in place public static void rotateArray(int[] array, int k) { reverse(array, 0, array.length - 1); reverse(array, 0, k - 1); reverse(array, k, array.length - 1); } public static void reverse(int[] array, int left, int right) { int temp; while (left < right) { temp = array[left]; array[left] = array[right]; array[right] = temp; left++; right--; } } // Q5 Multiplication of Numbers /* * There is an array A[N] of N numbers. You have to compose an array * Output[N] such that Output[i] will be equal to multiplication of all the * elements of A[N] except A[i]. Solve it without division operator and in * O(n). For example Output[0] will be multiplication of A[1] to A[N-1] and * Output[1] will be multiplication of A[0] and from A[2] to A[N-1]. * Example: A: {4, 3, 2, 1, 2} OUTPUT: {12, 16, 24, 48, 24} */ public static int[] multiplyNumbers(int[] num) { int n = num.length; int[] output = new int[n]; if (n == 0) return output; Arrays.fill(output, 1); int left = 1, right = 1; for (int i = 0; i < n; i++) { output[i] *= left; output[n - i - 1] *= right; left *= num[i]; right *= num[n - 1 - i]; } return output; } /* * Q6 Generate a prime list from 0 up to n, using The Sieve of Erantosthenes * param n The upper bound of the prime list (including n) param prime[] An * array of truth value whether a number is prime */ public static ArrayList<Integer> generatePrime(int n) { boolean[] prime = new boolean[n + 1]; if (n < 2) return new ArrayList<Integer>(); Arrays.fill(prime, true); prime[0] = false; prime[1] = false; int limit = (int) Math.sqrt((double) n); for (int i = 2; i <= limit; i++) { if (prime[i]) { for (int j = i * i; j <= n; j += i) prime[j] = false; } } ArrayList<Integer> res = new ArrayList<Integer>(); for (int i = 0; i <= n; i++) if (prime[i]) res.add(i); return res; } /* * Q7 Given a string of lowercase characters, reorder them such that the * same characters are at least distance d from each other. Input: { a, b, b * }, distance = 2 Output: { b, a, b } */ public static int findMax(int freqeuncy[], boolean excep[]) { int max_i = -1; int max = -1; for (int i = 0; i < 26; i++) { if (!excep[i] && freqeuncy[i] > 0 && freqeuncy[i] > max) { max = freqeuncy[i]; max_i = i; } } return max_i; } public static char[] keepDis(char[] str, int d) { int n = str.length; char[] res = new char[n]; int freqeuncy[] = new int[26]; for (int i = 0; i < n; i++) freqeuncy[str[i] - 'a']++; int distance[] = new int[26]; boolean excep[] = new boolean[26]; for (int i = 0; i < n; i++) { Arrays.fill(excep, false); boolean done = false; while (!done) { int j = findMax(freqeuncy, excep); if (j == -1) { System.out.println("Invalid inputs."); return res; } excep[j] = true; if (distance[j] <= 0) { res[i] = (char) (j + 'a'); freqeuncy[j]--; distance[j] = d; done = true; } } for (int k = 0; k < 26; k++) distance[k]--; } return res; } /* * Q8 Check whether an integer is a power of two. */ boolean mystery(int x) {// bug is when x == 0 return (x & (x - 1)) == 0; } boolean mysteryZero(int x) { return x != 0 && (x & (x - 1)) == 0; } /* * Q9 Number of 1 bits */ public static int countOneBitsCommon(int x) { int counter = 0; while ((x & 0x1) != 0) { counter++; x = x >> 1; } return counter; } public static int countOneBits(int x) { int counter = 0; while (x != 0) { counter++; x = x & (x - 1); } return counter; } /* * Q10 * Pre-order BST constructor */ public static int index = 0; public static TreeNode preorderConstructBST(int[] array, int min, int max){ if(index < array.length && array[index] < max && array[index] > min){ TreeNode root = new TreeNode(array[index++]); root.left = preorderConstructBST(array, min, root.val); root.right = preorderConstructBST(array, root.val, max); return root; } return null; } /* * Q11 * Deserialize a Binary Tree (any tree has an identical binary tree representation) */ public static void serialize(TreeNode root, ArrayList<Integer> array){ if(root == null) array.add(-1); else{ array.add(root.val); serialize(root.left, array); serialize(root.right, array); } } /* * Q12 * Excel sheet row numbers */ // start from 0 public static String convert(int row){ StringBuffer sb = new StringBuffer(""); sb.append((char)('a' + row % 26)); row /= 26; while(row != 0){ int index = (row - 1) % 26; row = (row - 1) / 26; sb.insert(0, (char)(index + 'a')); } return sb.toString(); } // start from 1 public static String convert2(int row){ StringBuffer sb = new StringBuffer(""); while(row != 0){ int index = row % 26; row /= 26; sb.insert(0, (char)(index + 'a' - 1)); } return sb.toString(); } // Q13 Search Young Tableau // O(n) public static boolean stepwise(int[][] table, int target){ if(table.length == 0) return false; if(table[0].length == 0) return false; int row = table.length; int col = table[0].length; if(target < table[0][0] || target > table[row - 1][col - 1]) return false; for(int i = 0, j = 0; i < row && j >= 0;){ if(table[i][j] == target) return true; else if(table[i][j] > target) j--; else i++; } return false; } // O(n^1.58) // row number ranges from top to bottom, column number ranges from left to right public static boolean quadPartition(int[][] table, int target, int left, int top, int right, int bottom){ if(left > right || top > bottom) return false; if(target < table[top][left] || target > table[bottom][right]) return false; int col = (right + left) / 2; int row = (top + bottom) / 2; if(table[row][col] == target) return true; else if (left == right && top == bottom) return false; if(table[row][col] > target){// upper left || upper right || bottom left return quadPartition(table, target, left, top, col, row) || quadPartition(table, target, col + 1, top, right, row) || quadPartition(table, target, left, row + 1, col, bottom); } else { // upper right || bottom right || bottom left return quadPartition(table, target, col + 1, top, right, bottom) || quadPartition(table, target, col + 1, row + 1, right, bottom) || quadPartition(table, target, left, row + 1, col, bottom); } } // do search on mid column, and then search on upper right side and bottom left side // if two sub-matrices are equal sizes, then O(n) public static boolean binaryPartition(int[][] table, int target, int left, int top, int right, int bottom){ if(left > right || top > bottom) return false; if(target < table[top][left] || target > table[bottom][right]) return false; int mid = (left + right) / 2; int row = top; // Could use binary search here which reduce complexity to O(lgn * lgn) while(row <= bottom && table[row][mid] <= target){ if(table[row][mid] == target) return true; row++; } // upper right || bottom left return binaryPartition(table, target, mid + 1, top, top, row - 1) || binaryPartition(table, target, left, row, mid - 1, bottom); } // Q14 Print boundary edges of a binary tree public static ArrayList<Integer> printEdges(TreeNode root){ ArrayList<Integer> res = new ArrayList<Integer>(); if(root == null) return res; res.add(root.val); printLeftBottomEdges(root.left, true, res); printBottomRightEdges(root.right, true, res); return res; } public static void printLeftBottomEdges(TreeNode root, boolean print, ArrayList<Integer> res){ if(root == null) return; if(print || (root.left == null && root.right == null)) res.add(root.val); printLeftBottomEdges(root.left, print, res); printLeftBottomEdges(root.right, print && root.left == null ? true : false, res); } public static void printBottomRightEdges(TreeNode root, boolean print, ArrayList<Integer> res){ if(root == null) return; printBottomRightEdges(root.left, print && root.right == null ? true : false, res); printBottomRightEdges(root.right, print, res); if(print || (root.left == null && root.right == null)) res.add(root.val); } // Q15 public static String Q15replace(String str, String pattern){ if(str == null || pattern == null || pattern.length() > str.length()) return str; StringBuilder sb = new StringBuilder(""); int lastStart = 0, curStart = 0, curEnd = 0; while(curStart != str.length()){ if(curStart + pattern.length() <= str.length() && match(str.substring(curStart, curStart + pattern.length()), pattern)){ sb.append(str.substring(lastStart, curStart)); if(sb.length() == 0 || sb.charAt(sb.length() - 1) != 'X') sb.append('X'); curEnd = curStart + pattern.length(); lastStart = curEnd; curStart = curEnd; } else { curStart++; } } if(curEnd != str.length()) sb.append(str.substring(lastStart, str.length())); return sb.toString(); } public static boolean match(String s, String p){ int i = 0; while(i != s.length() && i != p.length()){ if(s.charAt(i) != p.charAt(i)) return false; i++; } if(i == p.length()) return true; return false; } // Q16 from random7() to random10() // E(# of call random7) is 2.45. We throw away idx from 41 to 49 public static int random10(){ int row, col, idx; do { row = random7(); col = random7(); idx = col + (row - 1) * 7; } while(idx > 40); return 1 + (idx - 1) % 10; } public static int random7(){ return (int)(Math.random() * 7 + 1); } // E(# of call random7) is 2.21. We utilize integers from 41 to 49, and integers from 61 to 63 public static int random10_better(){ int row, col, idx; while(true){ row = random7(); col = random7(); idx = col + (row - 1) * 7; if(idx <= 40) return 1 + (idx - 1) % 10; row = row - 40; col = random7(); idx = col + (row - 1) * 7; if(idx <= 60) return 1 + (idx - 1) % 10; row = row - 60; col = random7(); idx = col + (row - 1) * 7; if(idx <= 20) return 1 + (idx - 1) % 10; } } //Q 17 // Largest Subtree which is a BST static TreeNode largestSubRoot = null; static int min, max, maxNodes; // min and max are for subtree, so the root.val should be outside of [min, max] public static TreeNode largestSubtree(TreeNode root){ findLargestSubtree(root); return largestSubRoot; } public static int findLargestSubtree(TreeNode root){ if(root == null) return 0; boolean isBST = true; int leftNodes = findLargestSubtree(root.left); int curMin = (leftNodes == 0) ? root.val : min; if(leftNodes == -1 || (leftNodes != 0 && root.val <= max)) // root.val in the range of subtree values, thus not BST isBST = false; int rightNodes = findLargestSubtree(root.right); int curMax = (rightNodes == 0) ? root.val : max; if(rightNodes == -1 || (rightNodes != 0 && root.val >= min)) // root.val in the range of subtree values, thus not BST isBST = false; if(isBST){ min = curMin; max = curMax; int totalNodes = leftNodes + rightNodes + 1; if(totalNodes > maxNodes){ maxNodes = totalNodes; largestSubRoot = root; } return totalNodes; } else return -1; } // Q18 static int maxNodesBST; static TreeNode largestBST; static TreeNode child; public int findLargestBST(TreeNode root, int min, int max){ if(root == null) return 0; if(min < root.val && root.val < max){ int leftNodes = findLargestBST(root.left, min, root.val); TreeNode leftChild = (leftNodes == 0) ? null : child; int rightNodes = findLargestBST(root.right, root.val, max); TreeNode rightChild = (rightNodes == 0) ? null : child; TreeNode parent = new TreeNode(root.val); parent.left = leftChild; parent.right = rightChild; child = parent; int totalNodes = leftNodes + rightNodes + 1; if(totalNodes > maxNodes){ maxNodes = totalNodes; largestBST = parent; } return totalNodes; } else { findLargestBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE); return 0; } } // Q19 public TreeNode constructFromList(LinkedListNode head, int start, int end){ if(start > end) return null; int mid = (start + end) / 2; TreeNode left = constructFromList(head, start, mid - 1); TreeNode parent = new TreeNode(head.value); parent.left = left; head = head.next; parent.right = constructFromList(head, mid + 1, end); return parent; } public static void main(String[] args) { // Q1 int[] A = { 1, 2, 3, 4, 5, 6, 7 }; int[] B = { 4, 5, 6, 7, 8, 9, 10, 11, 12 }; ArrayList<Integer> res = findIntersection(A, B); for (int i = 0; i < res.size(); i++) System.out.print(res.get(i) + " "); System.out.println(); // Q2 LinkedListNode head = new LinkedListNode(1); head.next = new LinkedListNode(2); head.next.next = new LinkedListNode(3); head = reverseLinkedListIteratively(head); while (head != null) { System.out.print(head.value + " "); head = head.next; } System.out.println(); // Q3 head = new LinkedListNode(1); head.next = new LinkedListNode(2); head.next.next = new LinkedListNode(3); head = reverseLinkedListRecursively(head); while (head != null) { System.out.print(head.value + " "); head = head.next; } System.out.println(); // Q4 rotateArray(A, 3); for (int i = 0; i < A.length; i++) System.out.print(A[i] + " "); System.out.println(); // Q5 A = new int[] { 4, 3, 2, 1, 2 }; A = multiplyNumbers(A); for (int i = 0; i < A.length; i++) System.out.print(A[i] + " "); System.out.println(); // Q6 ArrayList<Integer> primes = generatePrime(103); for (int i = 0; i < primes.size(); i++) System.out.print(primes.get(i) + " "); System.out.println(); // Q7 char[] charList = keepDis(new char[] { 'a', 'b', 'b' }, 2); for (int i = 0; i < charList.length; i++) System.out.print(charList[i] + " "); System.out.println(); // Q9 System.out.println("Count 1 bits: " + countOneBitsCommon(7)); System.out.println("Count 1 bits: " + countOneBits(7)); // Q10 int[] array = new int[]{7, 3, 1, 0, 2, 4, 6, 8}; TreeNode root = preorderConstructBST(array, Integer.MIN_VALUE, Integer.MAX_VALUE); System.out.println(); //Q11 ArrayList<Integer> selist = new ArrayList<Integer>(); serialize(root, selist); for(int i = 0; i < selist.size(); i++){ System.out.print(selist.get(i) + " "); } System.out.println(); // Q12 System.out.println(convert(730)); System.out.println(convert(27)); System.out.println(convert(3)); System.out.println(convert2(730)); System.out.println(convert2(27)); System.out.println(convert2(3)); //Q13 System.out.println("Search Young Tableau"); int[][] table = {{1, 4, 7, 11, 15}, {2, 5, 8, 12, 19}, {3, 6, 9, 16, 22}, {10, 13, 14, 17, 24}, {18, 21, 23, 26, 30}}; System.out.println(stepwise(table, 10)); System.out.println(quadPartition(table, 10, 0, 0, table[0].length - 1, table.length - 1)); System.out.println(binaryPartition(table, 10, 0, 0, table[0].length - 1, table.length - 1)); // Q14 int[] sorted_array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; TreeNode tree_root = TreeNode.construct(sorted_array, 0, sorted_array.length - 1); TreeNode.printLevel(tree_root); ArrayList<Integer> list = printEdges(tree_root); for(int i = 0; i < list.size(); i++) System.out.print(list.get(i) + " "); System.out.println(); // Q15 System.out.println(Q15replace("a", "a")); System.out.println(Q15replace("aa", "aa")); System.out.println(Q15replace("aa", "a")); System.out.println(Q15replace("aa", "aaa")); System.out.println(Q15replace("abc", "abc")); System.out.println(Q15replace("abcabc", "abc")); System.out.println(Q15replace("abcaabcaabc", "abc")); System.out.println(Q15replace("abcdeffdfegabcaaaabcab", "abc")); System.out.println(Q15replace("aabaaabaa", "aa")); // Q17 TreeNode root17 = new TreeNode(10); root17.left = new TreeNode(5); root17.left.left = new TreeNode(1); root17.left.right = new TreeNode(8); root17.right = new TreeNode(15); root17.right.right = new TreeNode(7); largestSubtree(root17); // Test. Pass. test.left will remain 6 no matter how left got changed TreeNode test = new TreeNode(5); TreeNode left = new TreeNode(6); TreeNode left_next = new TreeNode(7); test.left = left; // left = new TreeNode(8); left = left_next; // Q18 } }