2014年12月4日星期四

[LeetCode] Merge k Sorted Lists

Problem:

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

Code V1 ( Time Limit Exceeded):

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        if (lists == null || lists.size() == 0)
            return null;
        
        ListNode r = new ListNode(0);
        ListNode result = r;
        
        while (isEmpty(lists) == false) {
            Stack<Integer> s = new Stack<Integer>();
            for (int i = 0; i < lists.size(); i++) {
                if (lists.get(i) == null)
                    continue;
                if (s.empty() || s.peek() > lists.get(i).val) {
                    s.push(lists.get(i).val);
                    lists.set(i, lists.get(i).next);
                }
            }

            while (s.empty() == false) {
                r.next = new ListNode(s.pop());
                r = r.next;
            }
        }
        
        return result.next;
        
    }
    
    public boolean isEmpty(ArrayList<ListNode> lists) {
        for (int i = 0; i < lists.size(); i++) {
            if (lists.get(i) != null)
                return false;
        }
        return true;

    }

}


Code V2 (Memory Limit Exceeded):


/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        if (lists == null || lists.size() == 0)
            return null;
        
        ListNode r = new ListNode(0);
        ListNode result = r;
        
        while (isEmpty(lists) == false) {
            Stack<Integer> s = new Stack<Integer>();
            for (int i = 0; i < lists.size(); i++) {
                if (lists.get(i) == null)
                    continue;
                if (s.empty() || s.peek() > lists.get(i).val) {
                    s.push(lists.get(i).val);
                    lists.set(i, lists.get(i).next);
                }
            }

            while (s.empty() == false) {
                r.next = new ListNode(s.pop());
                r = r.next;
            }
        }
        
        return result.next;
        
    }
    
    public boolean isEmpty(ArrayList<ListNode> lists) {
        for (int i = 0; i < lists.size(); i++) {
            if (lists.get(i) != null)
                return false;
        }
        return true;

    }

}




Code V3 (Accepted):

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        
        PriorityQueue<ListNode> q = new PriorityQueue<ListNode>(100, new ListNodeComparator());
        for (int i = 0; i < lists.length; i++) {
            ListNode p = lists[i];
            if (p != null) {
                q.add(p);
            }
        }
        
        ListNode dummy = new ListNode(0);
        ListNode p = dummy;
        while (q.size() != 0) {
            ListNode node = q.poll();
            if (node.next != null) {
                q.add(node.next);
            }
            p.next = node;
            p = p.next;
        }
        
        return dummy.next;
    }
}

class ListNodeComparator implements Comparator<ListNode> {
  public int compare(ListNode n1, ListNode n2) {
    return n1.val - n2.val;
  }
}



2014年10月21日星期二

[LeetCode] Minimum Path Sum

Problem:
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

Solution:

Generally, dynamic programming is applicable to problems exhibiting the properties of overlapping subproblems, and optimal substructure.
For this kind of maximum/minimum problem(also for yes/no, count all possible solutions problems) , when the array cannot be sort or swapped, the solution should be dynamic programming. 

Attention:
Tried to solve the problem by recursion, but failed. Then, tried to use the for-loop, but tried to initialize the two dimensional array form the end to the start, which made it a little bit wired and hard to think.

Code:

public class Solution {
    public int minPathSum(int[][] grid) {
        //state: s[i][j] is minimum path sum from (0,0) to (i,j)
        //function: s[i][j] = min(s[i - 1][j], s[i][j - 1]) + cost[i][j]
        if (grid == null || grid.length == 0) {
            return 0;
        }
        
        int[][] s = new int[grid.length][grid[0].length];
        s[0][0] = grid[0][0];
        
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (i == 0 && j == 0) {
                    continue;
                }
                if (i - 1 < 0) {
                    s[i][j] = s[i][j - 1] + grid[i][j];
                    continue;
                }
                if (j - 1 < 0) {
                    s[i][j] = s[i - 1][j] + grid[i][j];
                    continue;
                }
                s[i][j] = Math.min(s[i - 1][j], s[i][j - 1]) + grid[i][j];
            }
        }
        
        return s[grid.length - 1][grid[0].length - 1];
    }
}

面试时可以问面试官的问题

Source:
https://docs.google.com/document/d/13vY5KA0teLBxlId6l81T4SRxBZ56CvOebtG8QnbFvlQ/edit

闲来没事可以问的问题:
Question to HR:
  • How would you describe the company culture?
  • What type of employees tend to excel at this company?
  • Can you tell me more about the interview process?
  • How would you describe the work environment here—collaborative or independent?
Hiring Manager: Your Future Boss
  • What is the ideal candidate?
  • What are some challenges one might face in this position?
  • What are the most important skillset for the job?
  • What are the backgrounds of people in the team?
  • What's a typical career path at the company for someone in this role?
  • If I am luck enough to get the job, what preparation would you suggest me do?
  • Learning/training opportunities
 The Executive or high level expert
  • How do you think this industry will change in the next five years?
  • What do you think is the competitive advantage of our company?
  • What's the company's biggest challenge? How is it planning to meet that challenge?
The Coworker
  • Could you please describe a typical day?
  • How would you describe the work environment at the company?
  • Share something about your background.
 
普适的问题:
  • What do you particularly like about the company?
  • What do you dislike about the company if there is any?
  • Could you tell me something about the projects that you are working on? The size of the team. The language the team is adopting?
以上的问题比较普适,不过最好还是能够在面试前去linkedin上搜搜相关信息,如果能对他正在做的东西进行提问会更让对方感到你是对这个position是特别感兴趣且上心的。
千万别问的问题!!:
1. 除了HR之外,不要讨论薪水的问题。
2. 别问我面试面的怎么样,结果怎么样。

2014年10月16日星期四

[LeetCode] LRU Cache

Problem:

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

Solution:


Cache should achieve the O(1) time complexity of get and set operation.
(1) To achieve the O(1) time complexity of look up operation, HashMap should be used to store the mapping relation between key and value(Node, in this solution).
(2) To achieve the O(1) time complexity of the invalidation operation of the least recently used item, double linked listed should be used. Every time, when there is a get operation, the accessed item will be moved to the head of the linked list. And the tail of the least recently used element of the cache.

Therefore, HashMap and Linked List should be used in this solution.

Code:

public class LRUCache {
    
    private int capacity;
    
    private Node head;
    private Node tail;
    
    private HashMap<Integer, Node> hs = new HashMap<Integer, Node>();
    
    private class Node {
        public int key;
        public int value;
        public Node pre;
        public Node next;
        
        public Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }
    
    public LRUCache(int capacity) {
        this.capacity = capacity;
        head = new Node(-1, -1);
        tail = new Node(-1, -1);
        
        head.next = tail;
        head.pre = null;
        tail.pre = head;
        tail.next = null;
    }
    
    public int get(int key) {
        if (!hs.containsKey(key)) {
            return -1;
        }
        
        Node n = hs.get(key);
        n.pre.next = n.next;
        n.next.pre = n.pre;
        
        n.next = head.next;
        head.next = n;
        n.pre = head;
        n.next.pre = n;
        
        return n.value;
        
    }
    
    public void set(int key, int value) {
// Attention, made a mistake here, did not consider if the key already exist in hs.
        if (hs.containsKey(key)) {
            Node n = hs.get(key);
            n.pre.next = n.next;
            n.next.pre = n.pre;
            hs.remove(key);
            capacity++;
        }
        
        if (capacity <= 0) {
            Node n = tail.pre;
            n.pre.next = n.next;
            n.next.pre = n.pre;
            hs.remove(n.key);
            
            capacity++;
        }
        
        Node temp = new Node(key, value);
        temp.next = head.next;
        head.next = temp;
        temp.pre = head;
        temp.next.pre = temp;
        
        hs.put(key, temp);
        
        capacity--;
        
        
    }
}

2014年10月15日星期三

[LeetCode] Max Points on a line

Problem:

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

Solution:

Assume there are two lines, line AB and AC.
AB and AC start from the same point A, then, if the slope of the two lines are equal, point A, B and C are on a line.
So, for each point A, calculate the slope of lines starts from A and connected to all other points in the points array. Store the slopes into HashMap.

Attention:

1) Duplicate points
For each point A in the array, when calculating the slope, if the value of A is equal to another point B, then the slope will not be calculated, and a variable "dup" will be used to store the number of duplicated points.
2) When the line is parallel to x-axis
Slope k = (y2 - y1) / (x2 - x1), and when x2 - x1 == 0 ( the line is parallel to x-axis )
The slope of the line will be infinity, and in Java, if a double is divided by zero, there will be an ArithmeticException, the program will blow up.
To fix it, assume the slope of lines parallel to x-axis is Integer.MIN_VALUE\
3) Double has two zeros, -0.0 and 0.0
Therefore, when calculating the slope, it should be like that:
slope = 0.0 + (double) (points[i].y - points[j].y) / (points[i].x - points[j].x);

Code:

/**
 * Definition for a point. class Point { int x; int y; Point() { x = 0; y = 0; }
 * Point(int a, int b) { x = a; y = b; } }
 */
public class Solution {
    public int maxPoints(Point[] points) {
        // Map<Integer,String> map = new HashMap<Integer,String>();
        if (points == null || points.length < 1)
            return 0;
        else if (points.length == 1)
            return 1;

        Map<Double, Integer> map = new HashMap<Double, Integer>();
        int length = points.length;

        int max = 1;

        for (int i = 0; i < length; i++) {
            int dup = 0;
            map.clear();

            // Input: [(0,0),(0,0)]
            // Output: 1
            // Expected: 2

            // maybe all points contained in the list are same points,and same
            // points' k is
            // represented by Integer.MIN_VALUE
            map.put((double) Integer.MIN_VALUE, 1);

            for (int j = i + 1; j < length; j++) {
                if (points[i].x == points[j].x && points[i].y == points[j].y) {
                    dup++;
                    continue;
                }

                // Zero and minus zero issue
                // Input: [(2,3),(3,3),(-5,3)]
                // Output: 2
                // Expected: 3
                double slope = (double) Integer.MIN_VALUE;
                if (points[i].x != points[j].x) {
                    slope = 0.0 + (double) (points[i].y - points[j].y)
                            / (points[i].x - points[j].x);
                }

                if (map.containsKey(slope)) {
                    map.put(slope, map.get(slope) + 1);
                } else {
                    map.put(slope, 2);
                }

            }

            for (int temp : map.values()) {
                max = temp + dup > max ? temp + dup : max;
            }
        }

        return max;
    }

}

2014年10月6日星期一

[LeetCode] Evaluate Reverse Polish Notation

Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are +, -, *, /. Each operand may be an integer or another expression.
Some examples:
  ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9
  ["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6
_____________________________________________________________________

1. About Reverse Polish Notation
Searched Wikipedia, and find it. Just remember the example below.
Polish Notation (Prefix Notation): + 3 4
Infix Notation: 3 + 4
Reverse Polish Notation (Postfix Notation): 3 4 +

2. Solutions
Traverse the String array token. if the string is a number, push it to stack. if it is an operator, pop 2 elements from the stack and take this two elements as operand, and push the result of the operation into stack. In the end, pop the result from stack and return.
2.1 My solution

Accepted

Time Complexity: O(n)
Space Complexity: O(n)
___________________code___________________
public class Solution {
    public int evalRPN(String[] tokens) {
        if (tokens == null) {
            return 0;
        }
       
        Stack s = new Stack();
       
        for (int i = 0; i < tokens.length; i++) {
            if (tokens[i].equals("+")) {
                int a = (int)s.pop();
                int b = (int)s.pop();
                s.push(b + a);
            } else if (tokens[i].equals("-")) {
                int a = (int)s.pop();
                int b = (int)s.pop();
                s.push(b - a);
            } else if (tokens[i].equals("*")) {
                int a = (int)s.pop();
                int b = (int)s.pop();
                s.push(b * a);
            } else if (tokens[i].equals("/")) {
                int a = (int)s.pop();
                int b = (int)s.pop();
                s.push(b / a);
            } else {
                s.push(Integer.parseInt(tokens[i]));
            }
        }
       
        int result = (int)s.pop();
        return result;
    }
}
___________________code___________________

2.2 Mistake Made
Used  token[i] == "/", which is grammatically correct but cannot really work.
Should use token[i].equals("/")  here.

2.3 Better solution
They used operations.contains(token), which I think is better.
http://answer.ninechapter.com/solutions/evaluate-reverse-polish-notation/

2014年10月3日星期五

[Leetcode] Maximum Product Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.

Solution 1:(Brute-Force approach)
s[i][j] represents the product of A.subarray(i,j). Initialize s, and update the value of max product each time. Then, after proceeding the nested for loop, return the max product.
However, this solution is Time Limit Exceeded
Time Complexity: O(n * n)
Space Complexity: O(n * n)
------------------code------------------
public class Solution {
    public int maxProduct(int[] A) {
        if (A == null || A.length == 0) {
            return 0;
        } else if (A.length == 1) {
            return A[0];
        }
     
        int length = A.length;
        int [][] s = new int[length][length];
        int maxProduct = Integer.MIN_VALUE;
     
        for (int i = 0; i < length; i++) {
            for (int j = 0; j < length; j++) {
                if (i >= j)
                    ;
                else if (i == j - 1)
                    s[i][j] = A[i] * A[j];
                else
                    s[i][j] = s[i][j - 1] * A[j];
                 
                if (maxProduct < s[i][j])
                    maxProduct = s[i][j];
            }
        }
     
        return maxProduct;
    }
}
------------------code------------------
Solution 2:
sMin[i] The min product subarray end with the index i.
sMax[i] The max product subarray end with the index i.
sMin[i] = The minimum of the three values: sMin[i - 1] * A[i], sMax[i - 1] * A[i], A[i]
sMin[i] = The maximum of the three values: sMin[i - 1] * A[i], sMax[i - 1] * A[i], A[i]

Accepted

Time Complexity: O(n)
Space Complexity: O(n)
------------------code------------------
public class Solution {
    public int maxProduct(int[] A) {
        if (A == null || A.length == 0) {
            return 0;
        } else if (A.length == 1) {
            return A[0];
        }
     
        int length = A.length;
        int [] sMax = new int[length];
        int [] sMin = new int[length];
        int maxProduct = A[0];
     
        sMax[0] = A[0];
        sMin[0] = A[0];
        for (int i = 1; i < length; i++) {
            sMax[i] = Math.max(Math.max(sMax[i - 1] * A[i], sMin[i - 1] * A[i]), A[i]);
            sMin[i] = Math.min(Math.min(sMax[i - 1] * A[i], sMin[i - 1] * A[i]), A[i]);
            maxProduct = Math.max(maxProduct, sMax[i]);
        }
     
        return maxProduct;
    }
}
------------------code------------------
There is also a O(n) solution that take O(1) space. See URL:
https://oj.leetcode.com/discuss/11923/sharing-my-solution-o-1-space-o-n-running-time

2014年9月16日星期二

[LeetCode] Gray Code

Gray Code -- binary numerical system where two successive values differ only in one bit (Wikipedia).

1. Background Information
1.1 Generate n-bit Gray Code
2-bit
00
01
11
10

3-bit
000
001
011
010
110
111
101
100

n-bit Gray Code can be generate from the list of (n -1) bit Gray Code using the following steps:
a. Let the list of (n - 1)-bit Gray Code be L1. Create another list L2 which is reverse of L1.
b. Modify the list L1 by prefixing a '0' in all codes of L1.
c. Modify the list L2 by prefixing a '1' in all codes of L2.
d. Concentrate L1 and L2. The concatenated list is required list of n-bits Gray Code.


1.2 n-th Gray Code
G(N) = (B(n) / 2) XOR B(n)


2. [LeetCode]
2.1 Problem
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.
For example, [0,2,3,1] is also a valid gray code sequence according to the above definition.
For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that.

2.2 Answer to this problem:
///////////////////////////////////////////////////////////////////////
public class Solution {
    public ArrayList<Integer> grayCode(int n) {
        //G(N) = (B(n)/2) XOR B(n)
        //Attention:
        // Two to the power of n, Use "Math.pow(2 , n);"
        // "^" Means XOR as an operator 
        
        ArrayList<Integer> result = new ArrayList<Integer>();

        for (int i = 0; i < Math.pow(2 , n); i++){
            int curGrayCode = (i / 2) ^ i;
            result.add(curGrayCode);
        }
     
        return result;
    }
}
///////////////////////////////////////////////////////////////////////