AdSense

Showing posts with label LeetCode. Show all posts
Showing posts with label LeetCode. Show all posts

Saturday, August 15, 2015

Merge K sorted linked lists/arrays revisited

K sorted arrays

I got a comment on my previous post Merge K sorted arrays, and I realized that there are much easier (and shorter) solutions to solve this problem. Here is the code snippet in both Java and Python.

Java:

public static List<Integer> merged (List<int[]> arrays){
  List<Integer> mergedArrays = new ArrayList<Integer> ();
  if (arrays == null || arrays.size() == 0){
   return mergedArrays;
  }
  for (int[] array : arrays){
   for (int i : array)
    mergedArrays.add(i);
  }
  Collections.sort(mergedArrays);
  return mergedArrays;
 }

Python:


def merged(lists):
    if lists is None or len(lists) == 0:
        return None
    mergedArray = [n for array in lists for n in array]
    return sorted(mergedArray)

Yeah, you can't disagree that the Pythonic way sometimes make things too easy to believe.

Why does this work:
Since in any case, we have to traverse the whole every element in the list of arrays, the complexity is O (mn), where m is the length of the list and n is the average length of each array.  Collections.sort() implements Timsort (see here, here and here) which on average has complexity O(nlogn). The time complexity is the same as using a priority queue, but with much shorter code.


K sorted lists

This gives me a reason to rethink the merge K sorted linked lists problem.
Unfortunately, since we need to return a linked list, we cannot use any built-in sorting methods.
I rewrite the code using Python. In Python, the built-in heapq only provides sorting based on natural order. Since the queue can sort tuples based on its first element, one solution could be wrapping the elements to be sorted to tuples (priority, element). See the code for detail[1].

import heapq
from mergeAndSort.ListNode import ListNode

class PriorityQueue(object):
    def __init__(self, initial = None, key=lambda x:x):
        self.key = key
        if initial:
            self._data = [(key(item), item) for item in initial]
            heapq.heapify(self._data)
        else:
            self._data = []

    def push(self, item):
        heapq.heappush(self._data, (self.key(item), item))

    def pop(self):
        return heapq.heappop(self._data)[1]

    def __len__(self):
        return len(self._data)

    def empty(self):
        return len(self._data) == 0

class ListNode(object):
    def __init__(self, val):
        self.val = val
        self.next = None

def mergeKLists(lists):
    if lists is None or len(lists) == 0:
            return None
    pq = PriorityQueue(key=lambda x:x.val)
    for n in lists:
        if n is not None:
            pq.push(n)
    head = ListNode(-1)
    h = head
    while not pq.empty():
        n = pq.pop()
        head.next = n
        head = head.next
        if n.next is not None:
            pq.push(n.next)
    return h.next

Comparison
Based on Leetcode's compiler, this Python implementation is not faster than the Java one. I'm sure there should be better solutions, please let me know.

Reference:
[1] http://stackoverflow.com/questions/8875706/python-heapq-with-custom-compare-predicate

Monday, May 25, 2015

All the Tree Traversal you need (not recursively!) Too

I got this idea of going through Leetcode again to learn Python in a more fun way. The first thing is basic data structures, and we definitely cannot forget binary tree.

Here are all the tree traversal solutions. All solutions are accepted on Leetcode. I only include the recursive version for the preorder traversal, since all others are similar and trivial.

If you need the Java version, see here.

Enjoy. :)


Preorder

The recursive way has two versions, the first one uses two functions while the second one use a nested recursive function inside the global one. See here for my post about the nested function in Python.

def preOrder(root):
    """
    iterative version
    :param root:
    :return:
    """
    rst = []
    if not root:
        return rst
    stack = [root]
    while stack:
        curr = stack.pop()
        if curr.right is not None:
            stack.append(curr.right)
        if curr.left is not None:
            stack.append(curr.left)
        rst.append(curr.val)
    return rst

def preOrderRec(root):
    """
    recursive version
    :param root:
    :return:
    """
    rst = []
    preorderHelper(root, rst)
    return rst

def preorderHelper(root, rst):
    if root is not None:
        rst.append(root.val)
        preorderHelper(root.left, rst)
        preorderHelper(root.right, rst)


def preOrderRec2(root):
    """
    nested inner recursive function
    :param root:
    :return:
    """
    rst = []

    def recursion(root):
        if root:
            rst.append(root.val)
            recursion(root.left)
            recursion(root.right)
    recursion(root)
    return rst


Inorder:


def inOrder(root):
    """
    in order traversal, iterative
    use a stack
    :param root:
    :return:
    """
    rst = []
    if not root:
        return rst
    stack = []
    while root or stack:
        if root:
            stack.append(root)
            root = root.left
        else:
            root = stack.pop()
            rst.append(root.val)
            root = root.right
    return rst



Postorder:
This one is quite different from the Java version. Since Python does not have any peek() method for the list class, I cannot use the way I used in the Java version (Actually, there is a way: use a deque, popleft() first and then appendleft(), but I don't think it's quite efficient).
In Python, I used two stacks. Basically, it looks like this:

  1. append the root to the first stack
  2. pop the root out the first stack and append it to the second stack
  3. append the left child followed by the right child of the root (if any exists)
  4. repeat 2 and 3 until the first stack is empty
  5. pop the nodes in the second stack and append it to the result list

Below the Python version is the Java version using the conventional method, you can compare the two method. :)


def postOrder(root):
    """
    iterative way, using two stacks
    :param root:
    :return:
    """
    rst = []
    if not root:
        return rst
    stack1 = [root]
    stack2 = []
    while stack1:
        curr = stack1.pop()
        if curr.left is not None:
            stack1.append(curr.left)
        if curr.right is not None:
            stack1.append(curr.right)
        stack2.append(curr)
    while stack2:
        rst.append(stack2.pop().val)
    return rst


Java version:

public ArrayList postorderTraversal(TreeNode root) {
        ArrayList rst = new ArrayList();
        if (root == null)
            return rst;
        Stack stack = new Stack();
        TreeNode curr = null;
        TreeNode prev = null;
        stack.push(root);
        while (!stack.empty())
        {
            curr = stack.peek();
            //prev == null, root
            //traverse down
            if (prev == null || prev.left == curr || prev.right == curr)
            {
                if (curr.left != null)
                    stack.push(curr.left);
                //need to traverse to the bottom of the tree first before goes to the right side
                else if (curr.right != null)
                    stack.push(curr.right);
            }
            // here comes the right side
            else if (curr.left == prev)
            {
                if (curr.right != null)
                    stack.push(curr.right);
            }
            //finally we can add nodes
            else
            {
                rst.add(curr.val);
                stack.pop();
            }
            prev = curr;
        }
        return rst;
    }


Level order:


from collections import deque

def levelOrder(root):
    """
    level order traversal
    :param root:
    :return:
    """
    rst = []
    if not root:
        return rst
    q = deque([root])
    while q:
        size = len(q)
        level = []
        for i in range(size):
            curr = q.popleft()
            if curr.left is not None:
                q.append(curr.left)
            if curr.right is not None:
                q.append(curr.right)
            level.append(curr.val)
        rst.append(level)
    return rst



Zigzag level order:

def zigzag(root):
    rst = []
    if not root:
        return rst
    thisLevel = [root]
    reverse = True
    while thisLevel:
        nextLevel = []
        level = []
        while thisLevel:
            curr = thisLevel.pop()
            level.append(curr.val)
            if reverse:
                if curr.left is not None:
                    nextLevel.append(curr.left)
                if curr.right is not None:
                    nextLevel.append(curr.right)
            else:
                if curr.right is not None:
                    nextLevel.append(curr.right)
                if curr.left is not None:
                    nextLevel.append(curr.left)

        thisLevel = nextLevel
        reverse = not reverse
        rst.append(level)
    return rst


Tuesday, March 17, 2015

Best time to buy and sell stork - IV


It took me a while to figure out the DP solution.
At each day, either it trades or it doesn't , the maximum profit will be between profits[i][j - 1] and the profit gain from selling at prices[j]. Now we need to the determine the maximum profit before we sell at prices[j], and that comes from transition i - 1 (tmpMax).
Consider we are at transition i - 1 and we just get our maximum profit, now we buy at prices[j] (not the same j as in the last paragraph), the maximum profit reduces to profit[i - 1][j] - prices[j], we compare this profit with the previous tmpMax, if it is smaller than tmpMax, we will not buy the stock at day j and leave the tmpMax as it it.

Since at maximum we can trade prices.length / 2 times, if k is larger than that, we simply use the solution in Best time to buy and sell stork - II to solve the problem.

Update 2016-09-26

Max profit of the day is price at the day - minimum cost of last day if we sell the stock today or last day's profit if we don't.
Minimum cost of the day is the minimum cost of last day if we don't buy the stock or today's price - maximum profit of last transaction if we buy the stock today.

public int maxProfit(int k, int[] prices) {
        if(prices == null || prices.length == 0)
            return 0;
        int len = prices.length;
        if(k >= len / 2)
            return quickSolve(prices);
        int[][] profits = new int[k + 1][len];
        for(int i = 1; i <= k; i++){
            int tmpMax = -prices[0];
            for(int j = 1; j < len; j++){
                profits[i][j] = Math.max(profits[i][j - 1], prices[j] + tmpMax);
                tmpMax = Math.max(tmpMax, profits[i - 1][j] - prices[j]);
            }
        }
        return profits[k][len - 1];
    }
    public int quickSolve(int[] prices){
        int profit = 0;
        for(int i = 1; i < prices.length; i++){
            profit += prices[i] - prices[i - 1] > 0 ? prices[i] - prices[i - 1] : 0;
        }
        return profit;
    }

Monday, March 9, 2015

Hamming weights

Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight).
For example, the 32-bit integer ’11' has binary representation 00000000000000000000000000001011, so the function should return 3.
Well, all I can say is, see Wikipedia.


public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int i) {
        i = i - ((i >> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
        return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
    }
}

I do have an easier approach, apparently LeetCode doesn't accept it.


public int hammingWeight(int n) {
        int ones = 0;
        while(n > 0){
            if((n & 1) > 0)
                ones++;
            n = (n >> 1);
        }
        return ones;
    }

Reverse bits

Reverse bits of a given 32 bits unsigned integer.
For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), return 964176192 (represented in binary as00111001011110000010100101000000).


I am still not good at bits operation. Even though now I can solve the problem by myself, it still takes certain time manner.


public class Solution {
    // you need treat n as an unsigned value
    public int reverseBits(int n) {
        if(n == 0)
            return n;
        int rst = 0;
        for (int b = 31; b >= 0; b--){
            rst |= ((n & 1) << b);
            n = n >> 1;
        }
        return rst;
    }
}

Wednesday, March 4, 2015

Zigzag conversion

The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)
P   A   H   N
A P L S I I G
Y   I   R
And then read line by line: "PAHNAPLSIIGYIR"
Write the code that will take a string and make this conversion given a number of rows:
string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) should return "PAHNAPLSIIGYIR".

I don't like this problem, the only thing this problem is testing is your patience, to find weird and unnecessary patterns.

So the approach. From the problem, we know that for any string, we should get a table like the following (e.g.,  nRows = 4):


So in the end, we want a string in the following order: 


Apparently, we need to find some pattern. First, the steps of each all-filled-column, which is: 

2 * (nRows - 1)

Next thing, the interval in between. There are several rules of the interval:

  • The interval should be greater than zero (of course...) and no larger than the step;
  • The index of the interval should be less than the length of the string;
  • No interval if we reach the end of the string;


So if you observe carefully, you will find that the interval follows the following equation: 

steps - 2 * i

where i is the row index. 



public String convert(String s, int nRows) {
        if(s == null || nRows == 1 || s.length() <= nRows)
            return s;
        int step = 2 * (nRows - 1);
        int count = 0;
        int l = s.length();
        char[] sArray = new char[l];
        for (int i = 0; i < nRows; i++){
            int interval = step - 2 * i;
            for (int j = i; j < l; j += step){
                sArray[count++] = s.charAt(j);
                if(interval > 0 && interval < step && interval + j < l && count < l)
                    sArray[count++] = s.charAt(j + interval);
            }
        }
        return new String(sArray);
    }


Reverse integer

I don't remember how many times I have solved this problem, but somehow I can never remember the exact way to solve the problem.

Basically, after dealing with the negative number issue, mod x by 10, add it to the result number, which is the result number in the previous loop * 10.

Do remember to take care of the overflow problem.


public int reverse(int x) {
        if(x > -10 && x < 10)
            return x;
        boolean isNegative = false;
        if(x < 0){
            isNegative = true;
            x = -x;
        }
        long num = 0;
        while(x > 0){
            num = num * 10l + (long)x % 10l;
            if(num > Integer.MAX_VALUE)
                return 0;
            x /= 10;
        }
        return isNegative ? -(int)num : (int)num;
    }

String to Integer(atoi)

Implement atoi to convert a string to an integer.
Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.
Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.
Update (2015-02-10):
The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button  to reset your code definition.
Requirements for atoi:
The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

I was talking to my friend about the atof post, and I realized that I didn't write this one. A very typical conversion problem, just need to be careful at every step.





public int atoi(String str) {
        if(str == null || str.length() == 0)
            return 0;
        str = str.trim();
        boolean isNegative = false;
        if(str.charAt(0) == '-' || str.charAt(0) == '+'){
            if(str.charAt(0) == '-')
                isNegative = true;
            str = str.substring(1);
        }
            
        long num = 0;
        for (int i = 0; i < str.length(); i++){
            if(!Character.isDigit(str.charAt(i))){
                return isNegative ? -(int)num : (int)num;
            }
            num = num * 10 + Character.getNumericValue(str.charAt(i));
            if(num > Integer.MAX_VALUE)
                return isNegative ? Integer.MIN_VALUE : Integer.MAX_VALUE;
        }
        return isNegative ? -(int)num : (int)num;
    }

Tuesday, March 3, 2015

Gray code

The gray code is a binary numeral system where two successive values differ in only one bit.
Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0.
For example, given n = 2, return [0,1,3,2]. Its gray code sequence is:
00 - 0
01 - 1
11 - 3
10 - 2
Note:
For a given n, a gray code sequence is not uniquely defined.
This problem is not a special one. Typical recursion follows Gray code rules. If n = 1, put 0 and 1 into the list and return. From n = 2, get grayCode(n - 1). Reverse the list ((0, 1) -> (1, 0)), add the reversed list by 1 << (n - 1), (1, 0) -> (11, 10), add the reversed list to the rst list and we are done!


public List grayCode(int n) {
        List rst = new ArrayList ();
        if (n <= 1){
            for(int i = 0; i <= n; i++)
                rst.add(i);
                return rst;
        }
        List reverseRst = grayCode(n - 1);
        rst = new ArrayList(reverseRst);
        Collections.reverse(reverseRst);
        int x = (1 << (n - 1));
        for(int i = 0; i < reverseRst.size(); i++){
            reverseRst.set(i, reverseRst.get(i) + x);
        }
        rst.addAll(reverseRst);
        return rst;
    }

Sunday, March 1, 2015

Two sum

Given an array of integers, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
Reduced my solution by couple lines.


public int[] twoSum(int[] numbers, int target) {
        int[] rst = new int[2];
        if (numbers == null || numbers.length == 0)
            return rst;
        Map num = new HashMap();
        for (int i = 0; i < numbers.length; i++){
            if (!num.containsKey(target - numbers[i]))
                num.put(numbers[i], i);
            else {
                rst[0] = num.get(target - numbers[i]) + 1;
                rst[1] = i + 1;
                return rst;
            }
        }
     return rst;   
    }

Wednesday, February 25, 2015

Min Stack

The stack can be implemented using LinkedList implementation. So the problem is how to track the minimum efficiently. One way to do it is to design a structure and store the minimum of all elements prior to head into the stack. Thus each node will also contain the information of the local minimum. The problem with this method is that there will be lots of duplicate data. For example, if I have a stack (0, 1, 2, 3, 4), the head is 4, with the minimum 0, every node stores 0, which is unnecessary and infeasible for very large stack.

So the question is, how can we do better?

One approach may be to use another List, or another stack to only track the local minimum. If the pushed node is smaller than the minimum of all existing nodes in the stack, push the node to the second stack. So for (0, 1, 2, 3, 4), we will have another list/stack only contains (0).
class MinStack {
    ListNode head;
    ListNode currMin;
    public MinStack() {
        head = null;
        currMin = null;
    }
    public MinStack(int val) {
        head = new ListNode(val);
        currMin = new ListNode(val);
    }
    
    public void push(int x) {
        if (head == null) {
            head = new ListNode(x);
            currMin = new ListNode(x);
        }
        else {
            ListNode node = new ListNode(x);
            node.next = head;
            head = node;
            //if there are two nodes with the same minimum value in the stack, 
            //if we delete the first one, or the one pushed in later, the minimum
            //of the stack is still the same value, thus we need to push the node
            //to the min stack as long as it equals the minimum
            if (x <= currMin.val) {
                //need to create a new node and push it
                //to the second list, 
                //otherwise the current node's next will points to next min
                //because we override it with the previous min
                ListNode tmp = node;
                tmp.next = currMin;
                currMin = tmp;
            }
        }
    }

    public void pop() {
        if (head == null)
            return;
        if (currMin.val == head.val) {
            currMin = currMin.next;
        }
        head = head.next;
    }

    public int top() {
        if (head == null)
            return -1;
        return head.val;
    }

    public int getMin() {
        if (head == null)
            return -1;
        return currMin.val;
    }
    private class ListNode{
        int val;
        ListNode next;
        public ListNode(int val) {
            this.val = val;
            next = null;
        }
    }
}

Tuesday, February 24, 2015

Rotate array

So how to do it in place? The answer is easy but tricky. Reverse the array 3 times. First reverse the whole array, second reverse (0, k - 1) and third reverse(k, n -1).
Take a look of the example.




public void rotate(int[] nums, int k) {
        if (nums == null || nums.length <= 1 || k <= 0 || k == nums.length)
            return;
        int l = nums.length;
        k = k % l;
        reverse(nums, 0, l - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, l - 1);
        
    }
    private void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    private void reverse(int[] nums, int start, int end) {
        while (start < end) {
            swap(nums, start, end);
            start++;
            end--;
        }
    }

Thursday, February 19, 2015

Read N Characters Given Read4 I & II

The API: int read4(char *buf) reads 4 characters at a time from a file.
The return value is the actual number of characters read. For example, it returns 3 if there is only 3 characters left in the file.
By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
Note: (for II)
The read function may be called multiple times.



Update: 2015 - 03 - 30
I realized that I understood the question wrong. The char* buf is the output array. The explanation below is correct, here is the updated code.


public int read4(char[] buff){
  return 4;
 }
 public int readN(char[] buff, int N){
  char[] tmp = new char[4];
  int index = 0, next = 0;
  while(index < N  && (next = read4(tmp)) != 0)
   for(int i = 0; i < next && index < N; buff[index++] = tmp[i++]);
  return index;
 }
 int curr = 0;
 public int readN2(char[] buff, int N){
  char[] tmp = new char[4];
  int next = 0;
  int length = 0;
  while(length < N && (next = read4(tmp)) != 0){
   for(int i = 0; i < next && length++ < N; buff[curr++] = tmp[i++]);
  }
  return length;
 }


It took me a while to understand how the read() method works. I implemented the read4() method, which makes the whole class easier to test.

Basically, if n >= length of the buf, we read the whole array and return its length. Otherwise, we track the position of the next character (nextChar) we will read next time we call readN() method, so we simply start from nextChar every time we call readN(). Since we initialize the out array (the one we stored the characters) with size n, each time we call readN(), we need to increment the length of the out array if the length of  buf is larger than n. I wrote another method read() to handle cases such as length of buff is smaller than n or the remaining unread length of array is smaller than n, reset index and nextChar to zero since we have reached the end of the array.

It is much easier to understand if you happen to know how Java implements read().


public class ReadN {
 static char[] out = new char[4];
 static int index = 0;
 static int nextChar = 0;
 
 private static int read4(char[] buf, int start, int length) {
  int len = length - start;
  if (len < 4) {
   int i = len;
   while (i > 0) {
    out[index++] = buf[start++];
    i--;
   } 
   return len;
  }
  for (int i = 0; i < 4; i++) {
   out[index++] = buf[start++];
  }
  return 4;
 }
 private static int read(char[] buf) {
  int total = 0;
  int length = buf.length;
  int start = nextChar;
  while (start < length) {
   total += read4(buf, start, length);
   start += 4;
  }
  index = 0;
  nextChar = 0;
  return total;
 }
 /**
  * I
  * @param buf
  * @param n
  * @return
  */
 public static int readN(char[] buf, int n) {
  if (buf == null)
   throw new NullPointerException("Null array!");
  int length = buf.length;
  out = new char[n];
  if (length <= n) {
   return read(buf);
  }
  int start = 0;
  int total = 0;
  while (start < n) {
   total += read4(buf, start, n);
   start += 4;
  }
  return total;
 }
 /**
  * II
  * call multiple times
  * @param buf
  * @param n
  * @return
  */
 public static int readNII(char[] buf, int n) {
  if (buf == null)
   throw new NullPointerException("Null array!");
  int length = buf.length;
  if (index == 0)
   out = new char[n];
  else {
   int incrementLen = length - nextChar >= n ? n : length - nextChar;
   char[] copy = new char[out.length + incrementLen];
   System.arraycopy(out, 0, copy, 0, out.length);
   out = copy;
   if (incrementLen < n)
    length = incrementLen;
  }
  if (length <= n) {
   return read(buf);
  }
  int start = nextChar;
  int total = 0;
  while (start < n) {
   total += read4(buf, start, n);
   if (start + 4 > n) {
    start = n;
    break;
   }
   start += 4;
  }
  nextChar = start;
  return total;
 }
 public static void main(String[] args) {
  //char[] input = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};
  //char[] input = {};
  //char[] input = {'a', 'b', 'c'};
  char[] input = {'a', 'b', 'c', 'd'};
  int total = 0;
  while (total < input.length) {
   total += readNII(input, 6);
  }
  System.out.println(total);

 }
}

Monday, February 9, 2015

Repeated DNA Sequences

The tricky part of this problem is that we cannot simply use a set to store or substrings: it will exceed memory limit. A smarter way is to use integers instead of strings. I use the rolling hash method, which is also used in the implement strStr() problem (see that problem for detail).


public class RepeatedDNA {
    private static final Map dna = new HashMap ();
    static {
        dna.put('A', 0);
        dna.put('C', 1);
        dna.put('G', 2);
        dna.put('T', 3);
    }
    private final int base = 29;
    public List findRepeatedDnaSequences(String s) {
        if (s == null)
            throw new NullPointerException("Null String!");
        //avoid duplicate sequence
        List rst = new ArrayList ();
        if (s.length() == 0)
            return rst;
        Set sequence = new HashSet ();
        long hashS = 0;
        for (int i = 0; i  < s.length(); i++) {
            if (i > 9) {
                hashS -= (long)Math.pow(base, 9) * dna.get(s.charAt(i - 10));
            }
            hashS = hashS * base + dna.get(s.charAt(i));
            if (i > 8 && !sequence.add(hashS)) {
                if (!rst.contains(s.substring(i - 9, i + 1)))
                    rst.add(s.substring(i - 9, i + 1));
            }
                
        }
        return rst;
    }
}

Thursday, February 5, 2015

Sort color

Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue.
Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
Note:
You are not suppose to use the library's sort function for this problem.

I have solved this four times, but I still couldn't remember it correctly. It is similar to dual pivot quick sort.
1. We take two pivots, the left one (pl) initialized at index 0 and the right one initialized at index A.length - 1;
2. Then we loop the array, if A[index] == 0, we swap it with pl, increment pl; if A[index] == 2, we swap it with pr, decrement pr.









public void sortColors(int[] A) {
        if (A == null || A.length < 2)
            return;
        int pl = 0;
        int pr = A.length - 1;
        int index = 0;
        while (index <= pr){
            if (A[index] == 0){
                swap(A, index++, pl++);
            }
            else if (A[index] == 2)
                swap(A, index, pr--);
            else
                index++;
        }
    }
    private void swap(int[] A, int i, int j){
        int tmp = A[i];
        A[i] = A[j];
        A[j] = tmp;
    }

Saturday, January 17, 2015

Two Sum III Data Structure design

Two Sum III - Data structure design

 Total Accepted: 311 Total Submissions: 1345
Design and implement a TwoSum class. It should support the following operations:add and find.
add - Add the number to an internal data structure.
find - Find if there exists any pair of numbers which sum is equal to the value.
For example,
add(1); add(3); add(5);
find(4) -> true
find(7) -> false

I use a list, I see other implementations that use a map. But my implementation is faster. O(1) add, and O(n) find.


import java.util.*;
public class TwoSum {
 private List list;
 public TwoSum() {
  list = new ArrayList ();
 }
 public void add(int num) {
  list.add(num);
 }
 public boolean find (int sum) {
  for (int i = 0; i < list.size(); i++) {
   if (list.contains(sum - list.get(i))) {
    if (list.indexOf(sum - list.get(i)) == i)
     continue;
    return true;
   }
  }
  return false;
 }
}

Thursday, January 15, 2015

Largest Number

Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.
Note: The result may be very large, so you need to return a string instead of an integer.

I was in the approach when I tried to sort the array. In fact, we do need to sort the array, but not in the traditional way.

If we look at the example, we will quickly figure out that we need to compare the most significant digit in the array, then probably the next, and so on. But the question is, how to do it in an acceptable time manner? Besides, why do we need to put 3 in front of 30?

Thinking the problem in another way: Randomly pick two numbers XYZ and ABC from the array, why do we want to put XYZ (ABC) in advance of ABC(XYC)? Because if we combine two numbers, XYZABC (ABCXYZ) will be larger than ABCXYZ (XYZABC). For example, 3 and 30, 330 is larger than 303, so we want to put 3 in front of 30.

So the only thing we need to do is to write a comparator to compare the concatenations of two numbers, and sort the entire array!

Easier than you thought, right?

Note on string.concat() and +
String.concat() will throw a NullPointerException if either of the string is null, but a + b will return, very interesting:


It treats b as b = "null". Another way to look at + can be like this: 


public static String plus(String a, String b) {
  StringBuilder sb = new StringBuilder();
  return sb.append(a).append(b).toString();
 }

The concat() method, from Java src is like this:


public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        char buf[] = new char[count + otherLen];
        getChars(0, count, buf, 0);
        str.getChars(0, otherLen, buf, count);
        return new String(0, count + otherLen, buf);
    }


Update: 2015 - 03 - 01
Update comparator method, note the number may be very large and overflow. 


private class StringComparator implements Comparator{
        public int compare(String s1, String s2){
            return (int)(Long.parseLong(s1 + s2) - Long.parseLong(s2 + s1));
        }
    }


public String largestNumber(int[] num) {
        if (num == null || num.length == 0)
            return "";
        String[] s = new String[num.length];
        for (int i = 0; i < num.length; i++) {
            s[i] = String.valueOf(num[i]);
        }
        Arrays.sort(s, new StringComparator ());
        String rst = "";
        for (int i = s.length - 1; i >= 0; i--) {
            rst += s[i];
        }
        int i = 0;
        while (i < rst.length() && rst.charAt(i) == '0')
            i++;
        if (i == rst.length())
            return "0";
        return rst.substring(i);
        
    }
    private class StringComparator implements Comparator {
        public int compare (String a, String b) {
            return Integer.parseInt(a.concat(b)) - Integer.parseInt(b.concat(a));
        }
    }

Monday, January 12, 2015

Implement strStr()

Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

If you are interested in a more advanced algorithm, KMP algorithm, look this. This post will implement this problem using a hash function. It is based on the rolling hash method. Basically, we calculate a hash function for the pattern string, or the needle, and compare it with the text string, or the haystack. The hash function is calculated as the following way:


The constant is chosen as 29 in this case. When comparing with the haystack, we remove the first part of the hash function and add the part for the new character. It's like a sliding window. 


public int strStr(String haystack, String needle) {
        if (haystack == null || needle == null) 
            return -1;
        if (haystack.length() == 0)
         return needle.length() == 0 ? 0 : -1;
        if (needle.length() == 0)
            return 0;
        if (haystack.length() < needle.length())
         return -1;
        int base = 29;
        int n = needle.length();
        long tmpBase = 1;
        long needleHash = 0;
        
        for (int i = n - 1; i >= 0; i--) {
         needleHash += (long)needle.charAt(i) * tmpBase;
            tmpBase *= base;
        }
        tmpBase = 1;
        long haystackHash = 0;
        for (int i = n - 1; i >= 0; i--) {
            haystackHash += (long)haystack.charAt(i) * tmpBase;
            tmpBase *= base;
        }
        if (haystackHash == needleHash)
            return 0;
        tmpBase /= base;
        for (int i = n; i < haystack.length(); i++) {
            haystackHash = (haystackHash - (long)haystack.charAt(i - n) * tmpBase) * base + (long)haystack.charAt(i);
            if (haystackHash == needleHash)
                return i - n + 1;
        }
        return -1;
    }

Update: 2015 - 01 - 19
As usual, my curiosity drove me to do the following performance test. It looks like KMP algorithm does hit the lower bound of the complexity:

P.S.: The test strings, if you are interested, are:
String haystack = "mississippimississippimississipippimissisippimissisippimissispimississippimississippimississippimississippimississippiabcabdabc"
String needle = "abcabdabc"


P.P.S: The KMP code:

public int strStr(String haystack, String needle) {
        if (needle == null || needle.length() == 0)
            return 0;
        if (haystack == null || haystack.length() == 0)
            return -1;
        if (haystack.length() < needle.length())
            return -1;
        int n = needle.length();
        int h = haystack.length();
        int[] PMT = getPMT(needle);
        int index_h = 0;
        int index_n = 0;
        while (index_h < h) {
            while(index_n >= 0 && haystack.charAt(index_h) != needle.charAt(index_n))
                index_n = PMT[index_n];
            index_h++;
            index_n++;
            if (index_n == n)
                return index_h - n;
        }
        return -1;
    }
    
    private int[] getPMT(String needle) {
        int[] PMT = new int[needle.length() + 1];
        PMT[0] = -1;
        PMT[1] = 0;
        for (int i = 2; i <= needle.length(); i++) {
            PMT[i] = (needle.charAt(i - 1) == needle.charAt(PMT[i - 1])) ? PMT[i - 1] + 1 : 0;
        }
        return PMT;
    }

Knuth - Morris - Pratt Algorithm: Let's give it a fancy name, pattern match

The initiative of studying this algorithm is because of this problem from LeetCode:
Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
It is an easy level problem, yet I spend my whole night figuring out this algorithm. And yes, I missed the Golden Globe (Congratulations to Eddie Redmayne, who portrayed one of my favorite physicists Stephen Hawking).

This algorithm is indeed a very interesting one. At first glance, it is very hard to understand, and require O(m) extra space, but if you really take some effort and try to understand it, you will realize how neat it can make the whole method.

Partial Match Table
Ok, start from Partial Match Table / Failure Function (PMT).  There are lots of resources to explain it, some of them are very fancy and complicated, I put the Wikipedia link here if you want some official explanation. Mine will be simpler. The partial match table matches the longest prefix and suffix that are equal of all substrings in a string. The prefix and suffix do not include the substring.
For example, consider string ="abcabdabc" will form a PMT as shown in the following table.


For an empty substring, the length is not defined, so we choose -1. Another reason to choose -1 is that when we use this table later in the pattern match, it will be easier for index incrementation. For a substring with length equals to 1, there is no prefix or suffix that doesn't include the whole substring, so the length = 0. For substring with length equal to 2 and 3, no equal prefix and suffix is found, so lengths still equal to 0. And we move on....

So how to calculate the PMT? Take a look at the table again. For "ab", since the length of equal prefix  & suffix = 0 for the previous substring "a", we compare the first character and the last character, since they are not equal, the length is still 0. Same for "abc", now it comes to "abca", since the the first and last character are equal, the length is 1. Or it is 0 + 1. Then it comes to "abcab", we already know from the last substring that the first character equals the last character (of the last substring), now we add one more character, we compare the second character with the last character (of this substring), the length is 2, or 1 + 1, You see the trend here? Every time, we compare the next character after the longest prefix (that equals to the suffix) with the last character, if the longest prefix = 0, we compare the first character with the last one, if the longest prefix = 1, we compare the second character, which has the index 1, with the last character. However, if the characters compared are not equal, the longest prefix = 0, i.e., :


PMT[i] = (ptrn.charAt(i - 1) == ptrn.charAt(PMT[i - 1])) ? (PMT[i - 1] + 1) : 0;

Yeah, as you know, it's DP.

What is the table used for? 

Considering a text string = "abcabcabdabcabcabdabdabc" (I am making it larger to look clearer), how to find the previous pattern string we showed above? You can say we compare each character in the pattern with the text string, if any character doesn't match, we slide the pattern string down to the next character in the text string that matches the first character in the pattern string. Yes, we can do that way, but it will take O(mn) time where m is the length of the pattern string and n is the length of the text string. So, can we do better? 

Look at the above figure, now we are at index 5 and the characters don't match. Since we already know that "abcab" has the longest prefix and suffix = 2, that means"ab" matches with "ab", now if we compare the character at index 5 in the text string with the character at index 2 (from the PMT table), they match, so next time we start from the characters at index 6 in the text string and index 3 at pattern string. If they don't match, say the following string, then from the table, the longest prefix of substring "ab" is 0, so unfortunately, we need to start over.



Using this algorithm allows us to trim off lots of unnecessary comparisons, the complexity is O(m + n) compared to the brutal force implementation. However, when the length of the string increases and mismatch increases, the complexity also increases.

public class KMP {
 private int[] getPMT(String ptrn) {
  int ptrnLen = ptrn.length();
  //partial match table
  int[] PMT = new int[ptrnLen + 1];
  PMT[0] = -1;
  PMT[1] = 0;
  for (int i = 2; i <= ptrnLen; i++) {
   PMT[i] = (ptrn.charAt(i - 1) == ptrn.charAt(PMT[i - 1])) ? (PMT[i - 1] + 1) : 0;
   System.out.println(i + ": " + PMT[i]);
  }
  return PMT;
  
     
    
 }
 public List searchSubString(String text, String ptrn) {
  if (text == null || ptrn == null)
   throw new NullPointerException("Null String(s)!");
  List rst = new ArrayList ();
  if (ptrn.length() == 0) {
   rst.add(0);
   return rst;
  }
  if (text.length() == 0 || text.length() < ptrn.length()) {
    return rst;
  }
  
  int indexT = 0;
  int indexP = 0;
  int ptrnLen = ptrn.length();
  int txtLen = text.length();
  int[] PMT = getPMT(ptrn);
  while (indexT < txtLen) {
   while (indexP >= 0 && text.charAt(indexT) != ptrn.charAt(indexP)) {
    indexP = PMT[indexP];
   }
   indexP++;
   indexT++;
   if (indexP == ptrnLen) {
    rst.add(indexT - ptrnLen);
    indexP = PMT[indexP];
   }
  }
  return rst;
 }


Source code can be found here: https://github.com/shirleyyoung0812/Knuth-Morris-Pratt-Algorithm.git

Sunday, January 11, 2015

Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space.
Some hints:
Could negative integers be palindromes? (ie, -1)
If you are thinking of converting the integer to string, note the restriction of using extra space.
You could also try reversing an integer. However, if you have solved the problem "Reverse Integer", you know that the reversed integer might overflow. How would you handle such case?
There is a more generic way of solving this problem.

In order to check if a number is a palindrome, we need to keep checking the first and last digit of the number. To get the last digit is trivial, i.e., x % 10, but how to get the first digit?

Thinking about how you will do to trim the last digit from a number? Divide the number by 10, right? So this time, we do it in the reverse way: multiply a number by 10: Start from 1, if x / divisor >= 10, it means we haven't reached the first digit, we need to keep multiply the divisor by 10, until we reach the first the digit. Note I did it this way at first:


int divisor = 1;
        while (divisor < x)
            divisor *= 10;
        divisor /= 10;

The divisor will overflow for large x, so no, this won't work.

The rest part is easy, keep checking the first and last digit and divide the divisor by 100 (each time we trim two digits).


public boolean isPalindrome(int x) {
        if (x < 0)
            return false;
        if (x > 0 && x < 10)
            return true;
        int divisor = 1;
        while (divisor < x)
            divisor *= 10;
        divisor /= 10;
        while (x > 0) {
            int right = x % 10;
            int left = x / divisor;
            if (left != right)
                return false;
            x -= (x / divisor * divisor);
            x /= 10;
            divisor /= 100;
        }
        return true;
    }