Friday, December 4, 2015

Flip Game II

You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip twoconsecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner.
Write a function to determine if the starting player can guarantee a win.
For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle "++" to become "+--+".
Follow up:
Derive your algorithm's runtime complexity.
Solution: backtracking, recursion
public class Solution {
    public boolean canWin(String s) {
        if (s == null || s.length() < 2) {
            return false;
        }
        
        for (int i = 0; i < s.length() - 1; i++) {
            if (s.substring(i, i + 2).equals("++")) {
                if (canWin(s.substring(0, i) + "--" + s.substring(i + 2)) == false) {
                    return true;
                }
            }
        }
        
        return false;
    }
}

Thursday, December 3, 2015

LeetCode - 🐶

1. Min Stack
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.

2. Binary Tree Paths
Given a binary tree, return all root-to-leaf paths.
For example, given the following binary tree:
   1
 /   \
2     3
 \
  5
All root-to-leaf paths are:

["1->2->5", "1->3"]

3. Unique Word Abbreviation
An abbreviation of a word follows the form <first letter><number><last letter>. Below are some examples of word abbreviations:
a) it                      --> it    (no abbreviation)

     1
b) d|o|g                   --> d1g

              1    1  1
     1---5----0----5--8
c) i|nternationalizatio|n  --> i18n

              1
     1---5----0
d) l|ocalizatio|n          --> l10n
Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary. A word's abbreviation is unique if no other word from the dictionary has the same abbreviation.
Example: 
Given dictionary = [ "deer", "door", "cake", "card" ]

isUnique("dear") -> false
isUnique("cart") -> true
isUnique("cane") -> false
isUnique("make") -> true

4. Summary Ranges
Given a sorted integer array without duplicates, return the summary of its ranges.

For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"].

5. Strobogrammatic number
A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down).
Write a function to determine if a number is strobogrammatic. The number is represented as a string.
For example, the numbers "69", "88", and "818" are all strobogrammatic.

6. Valid Parentheses
Given a string containing just the characters '('')''{''}''[' and ']', determine if the input string is valid.
The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.

Given a non-negative number represented as an array of digits, plus one to the number.
The digits are stored such that the most significant digit is at the head of the list.

Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
Note:
  • Given target value is a floating point.
  • You are guaranteed to have only one unique value in the BST that is closest to the target.

Given a string, determine if a permutation of the string could form a palindrome.
For example,
"code" -> False, "aab" -> True, "carerac" -> True.
Hint:
  1. Consider the palindromes of odd vs even length. What difference do you notice?
  2. Count the frequency of each character.
  3. If each character occurs even number of times, then it must be a palindrome. How about character which occurs odd number of times?

There is a fence with n posts, each post can be painted with one of the k colors.
You have to paint all the posts such that no more than two adjacent fence posts have the same color.
Return the total number of ways you can paint the fence.
Note:
n and k are non-negative integers.

You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip twoconsecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner.
Write a function to compute all possible states of the string after one valid move.
For example, given s = "++++", after one move, it may become one of the following states:
[
  "--++",
  "+--+",
  "++--"
]
If there is no valid move, return an empty list [].

Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.
Calling next() will return the next smallest number in the BST.
Note: next() and hasNext() should run in average O(1) time and uses O(h) memory, where h is the height of the tree.

Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target.
For example, given nums = [-2, 0, 1, 3], and target = 2.
Return 2. Because there are two triplets which sums are less than 2:
[-2, 0, 1]
[-2, 0, 3]
Follow up:
Could you solve it in O(n2) runtime?

Implement an iterator to flatten a 2d vector.
For example,
Given 2d vector =
[
  [1,2],
  [3],
  [4,5,6]
]
By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6].
Hint:
  1. How many variables do you need to keep track?
  2. Two variables is all you need. Try with x and y.
  3. Beware of empty rows. It could be the first few rows.
  4. To write correct code, think about the invariant to maintain. What is it?
  5. The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it?
  6. Not sure? Think about how you would implement hasNext(). Which is more complex?
  7. Common logic in two different places should be refactored into a common method.
Follow up:
As an added challenge, try to code it using only iterators in C++ or iterators in Java.

15. Flip Game II
You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip two consecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner.
Write a function to determine if the starting player can guarantee a win.
For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle "++" to become "+--+".
Follow up:
Derive your algorithm's runtime complexity.

A peak element is an element that is greater than its neighbors.
Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.
The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.
You may imagine that num[-1] = num[n] = -∞.
For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.
Note:
Your solution should be in logarithmic complexity.

Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
For example,
  • Given numerator = 1, denominator = 2, return "0.5".
  • Given numerator = 2, denominator = 1, return "2".
  • Given numerator = 2, denominator = 3, return "0.(6)".

According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
  2. Any live cell with two or three live neighbors lives on to the next generation.
  3. Any live cell with more than three live neighbors dies, as if by over-population..
  4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.
Follow up
  1. Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
  2. In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?

Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of conference rooms required.
For example,
Given [[0, 30],[5, 10],[15, 20]],
return 2.

20. 

Saturday, November 28, 2015

Strobogrammatic Number II

A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down).
Find all strobogrammatic numbers that are of length = n.
For example,
Given n = 2, return ["11","69","88","96"].
Hint:
  1. Try to use recursion and notice that it should recurse with n - 2 instead of n - 1.
Solution: recursion
Space complexity is stack space.
public class Solution {
    public List findStrobogrammatic(int n) {
        return helper(n, n);
    }
    
    public List helper(int remainLen, int n) {
        List res = new ArrayList();
        if (remainLen == 0) {
            return res;
        }
        if (remainLen == 1) {
            res.add("0");
            res.add("1");
            res.add("8");
            return res;
        }
        if (remainLen == 2) {
            if (remainLen != n) {
                res.add("00");  // 00 is invalid
            }
            res.add("11");
            res.add("69");
            res.add("88");
            res.add("96");
            return res;
        }
        
        List sub = helper(remainLen - 2, n);
        for (int i = 0; i < sub.size(); i++) {
            String s = sub.get(i);
            if (remainLen != n) {
                res.add("0" + s + "0");  // 0不能被加到最高位
            }
            res.add("1" + s + "1");
            res.add("6" + s + "9");
            res.add("8" + s + "8");
            res.add("9" + s + "6");
        }
        Collections.sort(res);
        return res;
    }
}

Thursday, November 26, 2015

Meeting Rooms II

Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of conference rooms required.
For example,
Given [[0, 30],[5, 10],[15, 20]],
return 2.
Solution1:
Sorting two arrays take O(nlogn) time. Compare takes O(n) time. Run time complexity is O(nlogn), space complexity is O(n).
/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class Solution {
    public int minMeetingRooms(Interval[] intervals) {
        if (intervals == null || intervals.length == 0) {
            return 0;
        }
        
        int[] start = new int[intervals.length];
        int[] end = new int[intervals.length];
        for (int i = 0; i < intervals.length; i++) {
            start[i] = intervals[i].start;
            end[i] = intervals[i].end;
        }
        
        Arrays.sort(start);
        Arrays.sort(end);
        
        int activeMeeting = 0;
        int minMeeting = 0;
        int i = 0;
        int j = 0;
        while (i < intervals.length && j < intervals.length) {
            if (start[i] < end[j]) {
                activeMeeting++;
                minMeeting = Math.max(activeMeeting, minMeeting);
                i++;
            } else {
                activeMeeting--;
                j++;
            }
        }
        
        return minMeeting;
    }
}
Solution2: Priority queue, Comparator
Use a priority queue to store the end times. Then we sort the intervals according to its start time. We iterate through the intervals. If the current start time is less than the earliest end time in the pq, numRooms++. Else, remove the earliest time from the pq. For each iteration, we also need to offer the current ending time into the pq.
Referencehttp://buttercola.blogspot.com/2015/08/leetcode-meeting-rooms-ii.html
/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class Solution {
    public int minMeetingRooms(Interval[] intervals) {
        if (intervals == null || intervals.length == 0) {
            return 0;
        }
        
        Arrays.sort(intervals, new IntervalComparator());
        PriorityQueue pq = new PriorityQueue();
        pq.offer(intervals[0].end);
        
        int minRooms = 1;
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i].start < pq.peek()) {
                minRooms++;
                pq.offer(intervals[i].end);
            } else {
                pq.poll();
                pq.offer(intervals[i].end);
            }
        }
        
        return minRooms;
    }
    
    public class IntervalComparator implements Comparator {
        @Override
        public int compare(Interval a, Interval b) {
            return a.start - b.start;
        }
    }
}

Game of Life

According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."
Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):
  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
  2. Any live cell with two or three live neighbors lives on to the next generation.
  3. Any live cell with more than three live neighbors dies, as if by over-population..
  4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
Write a function to compute the next state (after one update) of the board given its current state.
Follow up
  1. Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
  2. In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?
Solution:
每个细胞有初始状态0(死)和1(活),先定义一组中间状态,中间状态要求能看出一个细胞变化前后的生死情况。
Run time complexity is O(n ^ 2), constant space.
public class Solution {
    final int dead = 0;
    final int alive = 1;
    
    final int deadToDead = 0;    // 死->死
    final int aliveToAlive = 1;  // 活->活
    final int aliveToDead = 2;   // 活->死
    final int deadToAlive = 3;   // 死->活
    
    public void gameOfLife(int[][] board) {
        if (board == null) {
            return;
        }
        
        int row = board.length;
        int col = board[0].length;
        if (row == 0 || col == 0) {
            return;
        }
        
        int count = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                count = 0;
                // 统计周边生命情况
                if (i > 0 && j > 0 && isAliveOld(board[i - 1][j - 1])) {
                    count++;
                }
                if (i > 0 && isAliveOld(board[i - 1][j])) {
                    count++;
                }
                if (i > 0 && j < col - 1 && isAliveOld(board[i - 1][j + 1])) {
                    count++;
                }
                if (j > 0 && isAliveOld(board[i][j - 1])) {
                    count++;
                }
                if (j < col - 1 && isAliveOld(board[i][j + 1])) {
                    count++;
                }
                if (i < row - 1 && j > 0 && isAliveOld(board[i + 1][j - 1])) {
                    count++;
                }
                if (i < row - 1 && isAliveOld(board[i + 1][j])) {
                    count++;
                }
                if (i < row - 1 && j < col - 1 && isAliveOld(board[i + 1][j + 1])) {
                    count++;
                }
                
                // 判断当前细胞生病变化
                if (board[i][j] == alive) {
                    if (count < 2) {
                        // live cell with fewer than 2 live neighbors dies, under-population
                        board[i][j] = aliveToDead;
                    } else if (count == 2 || count == 3) {
                        // live cell with 2 or 3 live neighbors lives on to the next generation
                        board[i][j] = aliveToAlive;
                    } else {  
                        // live cell with more than 3 live neighbors dies, over-population
                        board[i][j] = aliveToDead;
                    }
                } else {
                    if (count == 3) {  
                        // dead cell with exactly 3 live neighbors becomes a live cell, reproduction
                        board[i][j] = deadToAlive;
                    } else {
                        board[i][j] = deadToDead;
                    }
                }
            }
        }
        
        // 根据变化后状态重新赋值
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (isAliveNew(board[i][j])) {
                    board[i][j] = alive;
                } else {
                    board[i][j] = dead;
                }
            }
        }
    }
    
    // 判断某个细胞在变化前是否存活
    public boolean isAliveOld(int cell) {
        if (cell == aliveToAlive || cell == aliveToDead) {
            return true;
        }
        return false;
    }
    
    // 判断某个细胞在变化后是否存活
    public boolean isAliveNew(int cell) {
        if (cell % 2 == 1) {  // 状态1和3
            return true;
        }
        return false;
    }
}

Wednesday, November 25, 2015

Fraction to Recurring Decimal

Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
For example,
  • Given numerator = 1, denominator = 2, return "0.5".
  • Given numerator = 2, denominator = 1, return "2".
  • Given numerator = 2, denominator = 3, return "0.(6)".
Solution: HashMap
Run time complexity is O(n), space complexity is O(n).
public class Solution {
    public String fractionToDecimal(int numerator, int denominator) {
        String result = "";
        // 处理正负号
        if (numerator > 0 && denominator < 0 || numerator < 0 && denominator > 0) {
            result += "-";
        }
        
        long num = Math.abs((long) numerator);
        long den = Math.abs((long) denominator);
        
        // 处理小数点前的位数
        result += num / den;
        if (num % den == 0) {
            return result;
        }
        
        // 如果num % den != 0说明有余数,加上小数点
        result += ".";
        
        num %= den;
        HashMap map = new HashMap();
        num *= 10;
        while (num % den != 0 && !map.containsKey(num)) {
            map.put(num, result.length());
            result += num / den;
            num %= den;
            num *= 10;
        }
        
        if (num % den == 0) {  // fractional part is not repeating
            result += num / den;
            return result;
        } else {
            String str = result.substring(0, map.get(num)) + "(" + result.substring(map.get(num)) + ")";
            return str;
        }
    }
}

Monday, November 23, 2015

Flatten 2D Vector

Implement an iterator to flatten a 2d vector.
For example,
Given 2d vector =
[
  [1,2],
  [3],
  [4,5,6]
]
By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,2,3,4,5,6].
Hint:
  1. How many variables do you need to keep track?
  2. Two variables is all you need. Try with x and y.
  3. Beware of empty rows. It could be the first few rows.
  4. To write correct code, think about the invariant to maintain. What is it?
  5. The invariant is x and y must always point to a valid point in the 2d vector. Should you maintain your invariant ahead of time or right when you need it?
  6. Not sure? Think about how you would implement hasNext(). Which is more complex?
  7. Common logic in two different places should be refactored into a common method.
Follow up:
As an added challenge, try to code it using only iterators in C++ or iterators in Java.
Solution:
public class Vector2D {
    List flat;
    int index;
    
    public Vector2D(List> vec2d) {
        index = 0;
        flat = new ArrayList();
        for (int i = 0; i < vec2d.size(); i++) {
            for (int j = 0; j < vec2d.get(i).size(); j++) {
                flat.add(vec2d.get(i).get(j));
            }
        }
    }

    public int next() {
        int val = flat.get(index);
        index++;
        return val;
    }

    public boolean hasNext() {
        return index < flat.size();
    }
}

/**
 * Your Vector2D object will be instantiated and called as such:
 * Vector2D i = new Vector2D(vec2d);
 * while (i.hasNext()) v[f()] = i.next();
 */
Follow Up: using only iterators in C++ or iterators in Java
Referencehttp://buttercola.blogspot.com/2015/08/leetcode-flatten-2d-vector.html
Inner iterator must be initilized as Collections.emptyIterator() because the method hasNext() first checks if the innerIterator.hasNext(), so the inner iterator itself must be an iterator at first. 
public class Vector2D {
    Iterator> outer;
    Iterator inner;
    
    public Vector2D(List> vec2d) {
        outer = vec2d.iterator();
        inner = Collections.emptyIterator();  // if outer == null, inner = outer.iterator() will throw exception
    }

    public int next() {
        return inner.next();
    }

    public boolean hasNext() {
        if (inner.hasNext()) {
            return true;
        }
        
        if (!outer.hasNext()) {
            return false;
        }
        
        inner = outer.next().iterator();
        while (!inner.hasNext() && outer.hasNext()) {
            inner = outer.next().iterator();
        }
        return inner.hasNext();
    }
}

/**
 * Your Vector2D object will be instantiated and called as such:
 * Vector2D i = new Vector2D(vec2d);
 * while (i.hasNext()) v[f()] = i.next();
 */

3Sum Smaller

Given an array of n integers nums and a target, find the number of index triplets i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target.
For example, given nums = [-2, 0, 1, 3], and target = 2.
Return 2. Because there are two triplets which sums are less than 2:
[-2, 0, 1]
[-2, 0, 3]
Follow up:
Could you solve it in O(n2) runtime?
Solution: run time complexity is O(n^3), constant space.
public class Solution {
    public int threeSumSmaller(int[] nums, int target) {
        if (nums == null || nums.length < 3) {
            return 0;
        }
        
        int count = 0;
        for (int i = 0; i < nums.length - 2; i++) {
            for (int j = i + 1; j < nums.length - 1; j++) {
                for (int k = j + 1; k < nums.length; k++) {
                    if (nums[i] + nums[j] + nums[k] < target) {
                        count++;
                    }
                }
            }
        }
        return count;
    }
}
Follow up: run time complexity is O(n^2), constant space.
public class Solution {
    public int threeSumSmaller(int[] nums, int target) {
        if (nums == null || nums.length < 3) {
            return 0;
        }
        
        Arrays.sort(nums);
        int count = 0;
        for (int i = 0; i < nums.length - 2; i++) {
            int left = i + 1;
            int right = nums.length - 1;
            while (left < right) {
                if (nums[i] + nums[left] + nums[right] < target) {
                    count = count + right - left;  // 一共有从right->left种情况
                    left++;
                } else {
                    right--;
                }
            }
        }
        return count;
    }
}

Flip Game

You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + and -, you and your friend take turns to flip two consecutive "++" into "--". The game ends when a person can no longer make a move and therefore the other person will be the winner.
Write a function to compute all possible states of the string after one valid move.
For example, given s = "++++", after one move, it may become one of the following states:
[
  "--++",
  "+--+",
  "++--"
]
If there is no valid move, return an empty list [].
Solution: run time complexity is O(n), space complexity is O(n).
public class Solution {
    public List generatePossibleNextMoves(String s) {
        List res = new ArrayList();
        if (s == null || s.length() <= 1) {
            return res;
        }
        
        int i = 0;
        while (i + 1 < s.length()) {
            if (s.charAt(i) == '+' && s.charAt(i + 1) == '+') {
                StringBuilder sb = new StringBuilder(s);
                sb.setCharAt(i, '-');
                sb.setCharAt(i + 1, '-');
                res.add(sb.toString());
            }
            i++;
        }
        
        return res;
    }
}
Or:
public class Solution {
    public List generatePossibleNextMoves(String s) {
        List res = new ArrayList();
        if (s == null || s.length() <= 1) {
            return res;
        }
        
        for (int i = 0; i < s.length() - 1; i++) {
            if (s.substring(i, i + 2).equals("++")) {
                res.add(s.substring(0, i) + "--" + s.substring(i + 2));
            }
        }
        
        return res;
    }
}

Paint Fence

There is a fence with n posts, each post can be painted with one of the k colors.
You have to paint all the posts such that no more than two adjacent fence posts have the same color.
Return the total number of ways you can paint the fence.
Note:
n and k are non-negative integers.
Solution1: dp
Define two DP arrays, diff[n] and same[i].
diff[i] means the number of ways for the fence i which has different color with fence i -1. 
same[i] means the number of ways if fence i has the same color with fence i - 1. 
递推公式:diff[i] = (k - 1) * (same[i - 1] + diff[i - 1])
Run time complexity is O(n), space complexity is O(n).
public class Solution {
    public int numWays(int n, int k) {
        if (n == 0 || k == 0) {
            return 0;
        }
        
        // i - 1 and i - 2 with the same color
        int[] same = new int[n];
        // i - 1 and i - 2 with the different color
        int[] diff = new int[n];
        
        same[0] = 0;
        diff[0] = k;
        
        for (int i = 1; i < n; i++) {
            same[i] = diff[i - 1];
            diff[i] = (k - 1) * (diff[i - 1] + same[i - 1]);
        }
        
        return same[n - 1] + diff[n - 1];
    }
}
Solution2:
Same logic as solution1, but constant space.
public class Solution {
    public int numWays(int n, int k) {
        if (n == 0 || k == 0) {
            return 0;
        }
        
        int preSame = 0;
        int preDiff = k;
        
        for (int i = 1; i < n; i++) {
            int same = preDiff;
            int diff = (k - 1) * (preDiff + preSame);
            
            preSame = same;
            preDiff = diff;
        }
        
        return preSame + preDiff;
    }
}

Palindrome Permutation

Given a string, determine if a permutation of the string could form a palindrome.
For example,
"code" -> False, "aab" -> True, "carerac" -> True.
Hint:
  1. Consider the palindromes of odd vs even length. What difference do you notice?
  2. Count the frequency of each character.
  3. If each character occurs even number of times, then it must be a palindrome. How about character which occurs odd number of times?
Solution1: HashMap
key存字母, value存字母出现的次数。如果每个字母都出现偶数次,true。如果只有一个字母出现奇数次,true。其余情况返回false。
Run time complexity is O(n), space complexity is O(n).
public class Solution {
    public boolean canPermutePalindrome(String s) {
        if (s == null || s.length() == 0) {
            return false;
        }
        
        HashMap map = new HashMap();
        for (int i = 0; i < s.length(); i++) {
            if (!map.containsKey(s.charAt(i))) {
                map.put(s.charAt(i), 1);
            } else {
                map.put(s.charAt(i), map.get(s.charAt(i)) + 1);
            }
        }
        
        int oddCount = 0;
        for (Map.Entry entry : map.entrySet()) {
            if (entry.getValue() % 2 != 0) {
                oddCount += 1;
            }
        }
        
        if (oddCount > 1) {
            return false;
        }
        
        return true;
    }
}
Solution2: HashSet
如果set中存在这个字母,从set中将其删除; 如果set中不存在,把字幕放进set里。
loop好之后,查看set的大小,如果大于1,说明有不止1个字母出现奇数次,不可以组成palindrome,返回false。
Run time complexity is O(n), space complexity is O(n).
public class Solution {
    public boolean canPermutePalindrome(String s) {
        if (s == null || s.length() == 0) {
            return false;
        }
        
        HashSet set = new HashSet();
        for (int i = 0; i < s.length(); i++) {
            if (set.contains(s.charAt(i))) {
                set.remove(s.charAt(i));
            } else {
                set.add(s.charAt(i));
            }
        }
        
        return set.size() <= 1;
    }
}

Sunday, November 22, 2015

Closest Binary Search Tree Value

Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
Note:
  • Given target value is a floating point.
  • You are guaranteed to have only one unique value in the BST that is closest to the target.
Solution: binary search
Run time complexity is O(logn), constant space.
注意:初始化 minDiff时候不能等于Integer.MAX_VALUE, 
test case: input[1500000000,1400000000], target -1500000000.0 过不了,因为最小差值超过Integer.MAX_VALUE了已经。
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int closestValue(TreeNode root, double target) {
        if (root == null) {
            return 0;
        }
        
        double minDiff = Math.abs(root.val - target);
        int value = root.val;
        while (root != null) {
            if (Math.abs(root.val - target) < minDiff) {
                minDiff = Math.abs(root.val - target);
                value = root.val;
            }
            
            if (root.val < target) {
                root = root.right;
            } else {
                root = root.left;
            }
        }
        
        return value;
    }
}