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
}
}