Thursday, August 6, 2015

Intersection of Two Linked Lists | Leetcode

Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:
A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3
begin to intersect at node c1.

Notes:
  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Your code should preferably run in O(n) time and use only O(1) memory.
Credits:
Special thanks to @stellari for adding this problem and creating all test cases.

---

Solution: Get the lengths of each list. Make them the same length by skipping the first few node of the longer list. For each of the remaining nodes, check each one to see if they are the same node. If not found, then return null.
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // Find the lengths of the two lists.
        int lengthA = getLength(headA);
        int lengthB = getLength(headB);
        
        // Make both lists the same length by skipping the
        // first few nodes of one of the lists if needed.
        for (int i = lengthB; i < lengthA; i++) {
            headA = headA.next;
        }
        for (int i = lengthA; i < lengthB; i++) {
            headB = headB.next;
        }
        
        // Check each node to see if they are the same node.
        while (headA != null) {
            if (headA == headB) return headA;
            headA = headA.next;
            headB = headB.next;
        }
        
        // No intersection found.
        return null;
    }
    
    private int getLength(ListNode node) {
        int length = 0;
        while (node != null) {
            length++;
            node = node.next;
        }
        return length;
    }
}

Min Stack | Leetcode

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
  • push(x) -- Push element x onto stack.
  • pop() -- Removes the element on top of the stack.
  • top() -- Get the top element.
  • getMin() -- Retrieve the minimum element in the stack.
---

Solution: Maintain two stacks internally. One is to hold all the elements. The other, minStack, is to only hold the current minimum elements. The current minimum element is always the top element of the minStack.
class MinStack {
    private LinkedList stack = new LinkedList<>();
    private LinkedList minStack = new LinkedList<>();
    
    public void push(int x) {
        stack.push(x);
        if (minStack.isEmpty() || x <= minStack.peek()) {
            minStack.push(x);
        }
    }

    public void pop() {
        int x = stack.pop();
        if (x == minStack.peek()) {
            minStack.pop();
        }
    }

    public int top() {
        return stack.peek();
    }

    public int getMin() {
        return minStack.peek();
    }
}

Find Minimum in Rotated Sorted Array II | Leetcode

Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

The array may contain duplicates.

---

Solution: I just copied and pasted my answer from http://choksheak.blogspot.com/2015/08/find-minimum-in-rotated-sorted-array.html and it got accepted right away.
public class Solution {
    public int findMin(int[] nums) {
        return findMin(nums, 0, nums.length - 1);
    } 
    
    private int findMin(int[] nums, int lo, int hi) {
        if (lo >= hi) return nums[hi];

        // If sub-array is sorted, return the first number.
        boolean isSorted = (nums[lo] < nums[hi]);
        if (isSorted) return nums[lo];

        // If sub-array is not sorted, then need to search in both halves.
        int mid = lo + (hi - lo) / 2;
        return Math.min(findMin(nums, lo, mid), findMin(nums, mid + 1, hi));
    }
}

Find Minimum in Rotated Sorted Array | Leetcode

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

You may assume no duplicate exists in the array.

---

Solution: Use a modified binary search. In each sub-array, if the first number is less than the last number, then this sub-array is sorted, so just return the first number. If this sub-array is not sorted, then break the sub-array into two halves and return the minimum of the minimum numbers from each half.
public class Solution {
    public int findMin(int[] nums) {
        return findMin(nums, 0, nums.length - 1);
    } 
    
    private int findMin(int[] nums, int lo, int hi) {
        if (lo >= hi) return nums[hi];

        // If sub-array is sorted, return the first number.
        boolean isSorted = (nums[lo] < nums[hi]);
        if (isSorted) return nums[lo];

        // If sub-array is not sorted, then need to search in both halves.
        int mid = lo + (hi - lo) / 2;
        return Math.min(findMin(nums, lo, mid), findMin(nums, mid + 1, hi));
    }
}

Wednesday, August 5, 2015

Maximum Product Subarray | Leetcode

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: Use 1D dynamic programming, where max[i] is the maximum product ending at i, and min[i] is the minimum product ending at i.

max[i] = max(a[i], (max[i - 1] * a[i]), (min[i - 1] * a[i]))
min[i] = min(a[i], (max[i - 1] * a[i]), (min[i - 1] * a[i]))

We need min[i] because if a[i] is negative, then min[i] * a[i] would produce the biggest product.
public class Solution {
    public int maxProduct(int[] nums) {
        int max = nums[0];
        int curMax = max;
        int curMin = max;

        for (int i = 1; i < nums.length; i++) {
            int n = nums[i];

            // We are changing curMax and curMin below,
            // so make sure to use the old value.
            int maxN = curMax * n;
            int minN = curMin * n;

            curMax = Math.max(Math.max(n, maxN), minN);
            curMin = Math.min(Math.min(n, minN), maxN);

            // Using "max = Math.max(max, curMax);"
            // here will exceed the leetcode time limit.
            if (curMax > max) max = curMax;
        }
        
        return max;
    }
}

Saturday, August 1, 2015

Reverse Words in a String | Leetcode

Given an input string, reverse the string word by word.

For example,
Given s = "the sky is blue",
return "blue is sky the".

Update (2015-02-12):
For C programmers: Try to solve it in-place in O(1) space.


Clarification:
  • What constitutes a word?
    A sequence of non-space characters constitutes a word.
  • Could the input string contain leading or trailing spaces?
    Yes. However, your reversed string should not contain leading or trailing spaces.
  • How about multiple spaces between two words?
    Reduce them to a single space in the reversed string.
---

Solution: Reverse the entire string. Then reverse each word. This means that we should refactor reverseChars() into its own method since we will use it a few times.

Remove all extra spaces. We could have done this when we reverse each word, but the code will be much simpler if we do this step separately.

It is better to do this in-place (update the same character array instead of creating a new array or StringBuilder) as that would require less memory. With a quick search online, I found that most solutions are not in-place and hence arguably are not optimal solutions for this problem.
public class Solution {
    public String reverseWords(String s) {
        if (s.length() == 0) return s;
        
        char[] a = s.toCharArray();
        
        // Reverse the entire string.
        reverseChars(a, 0, a.length - 1);

        // Reverse each word in place.
        int wordStart = -1;
        
        for (int i = 0; i < a.length; i++) {
            if (wordStart >= 0) {
                if (a[i] == ' ') {
                    reverseChars(a, wordStart, i - 1);
                    wordStart = -1;
                }
            } else {
                if (a[i] != ' ') {
                    wordStart = i;
                }
            }
        }

        // Remember to reverse the last word as we will not
        // hit a space at the end of it.
        if (wordStart >= 0) {
            reverseChars(a, wordStart, a.length - 1);
        }
        
        // Trim string and between words.
        int stringIndex = 0;
        boolean hasSpace = false;
        
        for (int i = 0; i < a.length; i++) {
            if (a[i] != ' ') {
                if (hasSpace) {
                    a[stringIndex++] = ' ';
                    hasSpace = false;
                }
                a[stringIndex++] = a[i];
            } else {
                if (stringIndex > 0) {
                    hasSpace = true;
                }
            }
        }
        
        return new String(a, 0, stringIndex);
    }
    
    private static void reverseChars(char[] a, int startInclusive, int endInclusive) {
        for (int i = startInclusive, j = endInclusive; i < j; i++, j--) {
            char c = a[i];
            a[i] = a[j];
            a[j] = c;
        }
    }
}

Evaluate Reverse Polish Notation | Leetcode

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

Solution: Use a stack to hold the numbers and the computation results. Iterate through the tokens from first to last. If you see a number, add it to the stack. If you see an operator, perform it on the top two elements of the stack, and then push the result back into the stack. When done, return the one and only value in the stack as the answer.
public class Solution {
    public int evalRPN(String[] tokens) {
        LinkedList<Integer> stack = new LinkedList<>();
        for (String token: tokens) {
            switch (token) {
                case "+":
                    stack.push(stack.pop() + stack.pop());
                    break;
                case "-":
                    stack.push(-stack.pop() + stack.pop());
                    break;
                case "*":
                    stack.push(stack.pop() * stack.pop());
                    break;
                case "/":
                    int denom = stack.pop();
                    stack.push(stack.pop() / denom);
                    break;
                default:
                    stack.push(Integer.parseInt(token));
            }
        }
        return stack.pop();
    }
}