Thursday, October 8, 2015

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

Understand the problem:
The question is a little bit tricky. 
There are only 2 conditions we return true for isUnique("word")
1. The abbr does not appear in the dict. 
2. The abbr is in the dict && the word appears one and only once in the dict. 

Code (Java): (WRONG SOLUTION)
public class ValidWordAbbr {
    private Map<String, String> map;
    public ValidWordAbbr(String[] dictionary) {
        this.map = new HashMap<>();
        
        for (String word : dictionary) {
            String abbr = toAbbr(word);
            if (map.containsKey(abbr)) {
                map.put(abbr, "");
            } else {
                map.put(abbr, word);
            }
        }
    }

    public boolean isUnique(String word) {
        String abbr = toAbbr(word);
        if (!map.containsKey(abbr) || map.get(abbr).equals(word)) {
            return true;
        } else {
            return false;
        }
    }
    
    private String toAbbr(String s) {
        if (s == null || s.length() <= 2) {
            return s;
        }
        
        int len = s.length() - 2;
        
        String result = s.charAt(0) + "" + len + s.charAt(s.length() - 1);
        
        return result;
    }
}
// Your ValidWordAbbr object will be instantiated and called as such:
// ValidWordAbbr vwa = new ValidWordAbbr(dictionary);
// vwa.isUnique("Word");
// vwa.isUnique("anotherWord");

Update on 9/26/15:

The solution above presumes that the dict does not contains duplicates. However, the OJ updates its test case that 
Input:["a","a"],isUnique("a")
Output:[false]
Expected:[true]

So the new solution we need to use two dictionaries, one save the abbr format and the other saves the original dict. The value stores the frequencies of each word. 

So how to determine if a word is unique in the abbrivation? There are still two cases to consider: 
1. If the abbr of the input word does not appear in the abbr dict, return true;
2. If the abbr of the input word DOES appears in the abbr dict, we must make sure the input word is in the dictionary AND the its abbreviation format can only appear once in the abbr dict. 
  -- Now here comes to the corner case that the dict contains duplicates. In this case, both the dict and abbr dict will store "a", 2. So in this way, a does not appear only once! So the solution to handle this edge case is we must make sure the word freq in the dict and abbr dict is exactly the same. So we can make sure the word has no other duplicated abbrivations in the abbr dict. 

Code (Java):
public class ValidWordAbbr {
    private Map<String, Integer> abbrDict;
    private Map<String, Integer> dict;
    public ValidWordAbbr(String[] dictionary) {
        abbrDict = new HashMap<>();
        dict = new HashMap<>();
        
        
        for (String word : dictionary) {
            
            if (dict.containsKey(word)) {
                int freq = dict.get(word);
                dict.put(word, freq + 1);
            } else {
                dict.put(word, 1);
            }
            
            String abbr = abbreviation(word);
            if (abbrDict.containsKey(abbr)) {
                int freq = abbrDict.get(abbr);
                abbrDict.put(abbr, freq + 1);
            } else {
                abbrDict.put(abbr, 1);
            }
        }
    }

    public boolean isUnique(String word) {
        if (word == null || word.length() == 0) {
            return true;
        }
        
        String abbr = abbreviation(word);
        if (!abbrDict.containsKey(abbr)) {
            return true;
        } else {
            if (dict.containsKey(word) && dict.get(word) == abbrDict.get(abbr)) {
                return true;
            }
        }
        
        return false;
    }
    
    private String abbreviation(String word) {
        if (word.length() <= 2) {
            return word;
        }
        
        StringBuffer sb = new StringBuffer();
        sb.append(word.charAt(0));
        sb.append(word.length() - 2);
        sb.append(word.charAt(word.length() - 1));
        
        return sb.toString();
    }
}

Update on 11/9/15:
public class ValidWordAbbr {
    private Set<String> uniqueDict;
    private Map<String, String> abbrDict;

    public ValidWordAbbr(String[] dictionary) {
        uniqueDict = new HashSet<>();
        abbrDict = new HashMap<>();
        
        for (String word : dictionary) {
            if (!uniqueDict.contains(word)) {
                String abbr = getAbbr(word);
                if (!abbrDict.containsKey(abbr)) {
                    abbrDict.put(abbr, word);
                } else {
                    abbrDict.put(abbr, "");
                }
                
                uniqueDict.add(word);
            }
        }
    }

    public boolean isUnique(String word) {
        if (word == null || word.length() == 0) {
            return true;
        }
        
        String abbr = getAbbr(word);
        if (!abbrDict.containsKey(abbr) || abbrDict.get(abbr).equals(word)) {
            return true;
        } else {
            return false;
        }
    }
    
    private String getAbbr(String word) {
        if (word == null || word.length() < 3) {
            return word;
        }
        
        StringBuffer sb = new StringBuffer();
        sb.append(word.charAt(0));
        sb.append(word.length() - 2);
        sb.append(word.charAt(word.length() - 1));
        
        return sb.toString();

    }
    
}


// Your ValidWordAbbr object will be instantiated and called as such:
// ValidWordAbbr vwa = new ValidWordAbbr(dictionary);
// vwa.isUnique("Word");
// vwa.isUnique("anotherWord");


Leetcode: Word Pattern

Given a pattern and a string str, find if str follows the same pattern.
Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str.
Examples:
  1. pattern = "abba", str = "dog cat cat dog" should return true.
  2. pattern = "abba", str = "dog cat cat fish" should return false.
  3. pattern = "aaaa", str = "dog cat cat dog" should return false.
  4. pattern = "abba", str = "dog dog dog dog" should return false.
Notes:
  1. patterncontains only lowercase alphabetical letters, and str contains words separated by a single space. Each word in str contains only lowercase alphabetical letters.
  2. Both pattern and str do not have leading or trailing spaces.
  3. Each letter in pattern must map to a word with length that is at least 1.
Understand the problem:
The problem can be solved by using hash map. Note that some edge cases must be considered:
1. It must be a one-one mapping. e.g. 
"abba", "dog dog dog dog" => false, since a and b maps to the dog.
"aaaa", "dog cat cat dog" => false, since a maps to both dog and cat. 

So we may use two hash tables to maintain such a one-one mapping relationship. Note that in Java we may use map.containsValue(). 

2. The length of the pattern and number of tokens in the str must be the same. Otherwise, return false; 

Code (Java):
public class Solution {
    public boolean wordPattern(String pattern, String str) {
        if (pattern == null || pattern.length() == 0 || str == null || str.length() == 0) {
            return false;
        }

        String[] tokens = str.split(" ");
        
        if (pattern.length() != tokens.length) {
            return false;
        }

        Map<String, Character> inverseMap = new HashMap<>();
        Map<Character, String> map = new HashMap();
        
        int i = 0;
        for (i = 0; i < pattern.length(); i++) {
            char digit = pattern.charAt(i);
            
            String token = tokens[i];
            
            // Check the one-one mapping
            if (!map.containsKey(digit) && !inverseMap.containsKey(token)) {
                map.put(digit, token);
                inverseMap.put(token, digit);
            } else if (map.containsKey(digit) && inverseMap.containsKey(token)) {
                String token1 = map.get(digit);
                char digit1 = inverseMap.get(token);
                
                if (!token1.equals(token) || digit != digit1) {
                    return false;
                }
            } else {
                return false;
            }
        }
        
        return true;
    }
}

Wednesday, September 30, 2015

Leetcode: Walls and Gates

You are given a m x n 2D grid initialized with these three possible values.
  1. -1 - A wall or an obstacle.
  2. 0 - A gate.
  3. INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 to represent INF as you may assume that the distance to a gate is less than2147483647.
Fill each empty room with the distance to its nearest gate. If it is impossible to reach a gate, it should be filled with INF.
For example, given the 2D grid:
INF  -1  0  INF
INF INF INF  -1
INF  -1 INF  -1
  0  -1 INF INF
After running your function, the 2D grid should be:
  3  -1   0   1
  2   2   1  -1
  1  -1   2  -1
  0  -1   3   4
Understand the problem:
It is very classic backtracking problem. We can start from each gate (0 point), and searching for its neighbors. We can either use DFS or BFS solution.

A DFS Solution:
public class Solution {
    public void wallsAndGates(int[][] rooms) {
        if (rooms == null || rooms.length == 0) {
            return;
        }
        
        int m = rooms.length;
        int n = rooms[0].length;
        
        boolean[][] visited = new boolean[m][n];
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (rooms[i][j] == 0) {
                    wallsAndGatesHelper(i, j, 0, visited, rooms);
                }
            }
        }
    }
    
    private void wallsAndGatesHelper(int row, int col, int distance, boolean[][] visited, int[][] rooms) {
        int rows = rooms.length;
        int cols = rooms[0].length;
        
        if (row < 0 || row >= rows || col < 0 || col >= cols) {
            return;
        }
        
        // visited
        if (visited[row][col]) {
            return;
        }
        
        // Is wall?
        if (rooms[row][col] == -1) {
            return;
        }
        
        // Distance greater than current
        if (distance > rooms[row][col]) {
            return;
        }
        
        
        // Mark as visited
        visited[row][col] = true;
        
        if (distance < rooms[row][col]) {
            rooms[row][col] = distance;
        }
        
        // go up, down, left and right
        wallsAndGatesHelper(row - 1, col, distance + 1, visited, rooms);
        wallsAndGatesHelper(row + 1, col, distance + 1, visited, rooms);
        wallsAndGatesHelper(row, col - 1, distance + 1, visited, rooms);
        wallsAndGatesHelper(row, col + 1, distance + 1, visited, rooms);
        
        // Mark as unvisited
        visited[row][col] = false;
    }
}

A BFS Solution:
public class Solution {
    public void wallsAndGates(int[][] rooms) {
        if (rooms == null || rooms.length == 0) {
            return;
        }
        
        int m = rooms.length;
        int n = rooms[0].length;
        
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (rooms[i][j] == 0) {
                    wallsAndGatesHelper(i, j, 0, rooms, queue);
                }
            }
        }
    }
    
    private void wallsAndGatesHelper(int row, int col, int distance, int[][] rooms, Queue<Integer> queue) {
        fill(row, col, distance, rooms, queue);
        
        int m = rooms.length;
        int n = rooms[0].length;
        
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int cord = queue.poll();
                int x = cord / n;
                int y = cord % n;
            
                fill(x - 1, y, distance + 1, rooms, queue);
                fill(x + 1, y, distance + 1, rooms, queue);
                fill(x, y - 1, distance + 1, rooms, queue);
                fill(x, y + 1, distance + 1, rooms, queue);
            
            }
            distance++;
        }
    }
    
    private void fill (int row, int col, int distance, int[][] rooms, Queue<Integer> queue) {
        int m = rooms.length;
        int n = rooms[0].length;
        
        if (row < 0 || row >= m || col < 0 || col >= n) {
            return;
        }
        
        if (rooms[row][col] == -1) {
            return;
        }
        
        if (distance > rooms[row][col]) {
            return;
        }
        
        if (distance < rooms[row][col]) {
            rooms[row][col] = distance;
        }
        
        int cord = row * n + col;
        queue.offer(cord);
    }
}

Leetcode: Move Zeroes

Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
Note:
  1. You must do this in-place without making a copy of the array.
  2. Minimize the total number of operations.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
Understand the problem:
Since the problem requires to maintain the relative order of the array, we cannot simply swap the numbers in the array. 

One simple way is very similar to remove the duplicated numbers in the array. In the first pass, we move all the non-zero elements upfront and fill out all the zero slots. Then we just need to append 0s at the end of the array.

Code (Java):
public class Solution {
    public void moveZeroes(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        
        int i = 0;
        int j = 0;
        
        // Step 1: compress the nums array by filling out the 0s
        while (i < nums.length) {
            if (nums[i] != 0) {
                nums[j] = nums[i];
                j++;
                i++;
            } else {
                i++;
            }
        }
        
        // Append 0s to the end
        while (j < nums.length) {
            nums[j] = 0;
            j++;
        }
    }
}

Tuesday, September 29, 2015

Leetcode: Peeking Iterator

Given an Iterator class interface with methods: next() and hasNext(), design and implement a PeekingIterator that support the peek() operation -- it essentially peek() at the element that will be returned by the next call to next().

Here is an example. Assume that the iterator is initialized to the beginning of the list: [1, 2, 3].
Call next() gets you 1, the first element in the list.
Now you call peek() and it returns 2, the next element. Calling next() after that still return 2.
You call next() the final time and it returns 3, the last element. Calling hasNext() after that should return false.
Hint:
  1. Think of "looking ahead". You want to cache the next element.
  2. Is one variable sufficient? Why or why not?
  3. Test your design with call order of peek() before next() vs next() before peek().
  4. For a clean implementation, check out Google's guava library source code.
Follow up: How would you extend your design to be generic and work with all types, not just integer?
Code (Java):
// Java Iterator interface reference:
// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
class PeekingIterator implements Iterator<Integer> {
    private Iterator<Integer> iterator;
    private int peekedElement;
    private boolean hasPeekedElement;

 public PeekingIterator(Iterator<Integer> iterator) {
     // initialize any member here.
     this.iterator = iterator;
     if (iterator.hasNext()) {
         hasPeekedElement = true;
         peekedElement = iterator.next();
     }
 }

    // Returns the next element in the iteration without advancing the iterator.
 public Integer peek() {
        return peekedElement;
 }

 // hasNext() and next() should behave the same as in the Iterator interface.
 // Override them if needed.
 @Override
 public Integer next() {
     int ret = peekedElement;
     if (iterator.hasNext()) {
         peekedElement = iterator.next();
     } else {
         hasPeekedElement = false;
     }
     return ret;
 }

 @Override
 public boolean hasNext() {
     return iterator.hasNext() || hasPeekedElement;
 }
}


Update on 10/14/15:
// Java Iterator interface reference:
// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html
class PeekingIterator implements Iterator<Integer> {
    private Iterator<Integer> it;
    private int peakElement;
    private boolean peaked;
 public PeekingIterator(Iterator<Integer> iterator) {
     // initialize any member here.
     this.it = iterator;
     peakElement = 0;
     peaked = false;
 }

    // Returns the next element in the iteration without advancing the iterator.
 public Integer peek() {
        if (!peaked) {
            peakElement = it.next();
            peaked = true;
        }
        return peakElement;
 }

 // hasNext() and next() should behave the same as in the Iterator interface.
 // Override them if needed.
 @Override
 public Integer next() {
     int ans = 0;
     if (peaked) {
         ans = peakElement;
         peaked = false;
     } else {
         ans = it.next();
     }
     
     return ans;
 }

 @Override
 public boolean hasNext() {
     return peaked == true || it.hasNext();
 }
}

Wednesday, September 16, 2015

Leetcode: Dungeon Game

The demons had captured the princess (P) and imprisoned her in the bottom-right corner of a dungeon. The dungeon consists of M x N rooms laid out in a 2D grid. Our valiant knight (K) was initially positioned in the top-left room and must fight his way through the dungeon to rescue the princess.
The knight has an initial health point represented by a positive integer. If at any point his health point drops to 0 or below, he dies immediately.
Some of the rooms are guarded by demons, so the knight loses health (negative integers) upon entering these rooms; other rooms are either empty (0's) or contain magic orbs that increase the knight's health (positive integers).
In order to reach the princess as quickly as possible, the knight decides to move only rightward or downward in each step.

Write a function to determine the knight's minimum initial health so that he is able to rescue the princess.
For example, given the dungeon below, the initial health of the knight must be at least 7 if he follows the optimal path RIGHT-> RIGHT -> DOWN -> DOWN.
-2 (K)-33
-5-101
1030-5 (P)

Notes:
  • The knight's health has no upper bound.
  • Any room can contain threats or power-ups, even the first room the knight enters and the bottom-right room where the princess is imprisoned.
Credits:
Special thanks to @stellari for adding this problem and creating all test cases.
Understand the problem:
A matrix DP problem. We could start from the bottom-right corner, i.e, dungeon[m - 1][n - 1]. 

  -- Define dp[i][j] means the min HP value from i, j to the bottom-right corner. 
  -- Initialization: dp[m - 1][n - 1] = Math.max(1, 1 - dungeon[m - 1][n - 1]);
                          dp[m - 1][j] = Math.max(1, dp[m - 1][j + 1] - dungeon[m - 1][j]);
                          dp[i][n - 1] = Math.max(1, dp[i + 1][n - 1] - dungeon[i][n - 1]);
  -- Transit function: dp[i][j] = Math.max(1, Math.min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j]);
  -- Final state dp[0][0].


Code (Java):
public class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        if (dungeon == null) {
            return 0;
        }
        
        int m = dungeon.length;
        int n = dungeon[0].length;
        
        int[][] dp = new int[m][n];
        
        dp[m - 1][n - 1] = Math.max(1, 1 - dungeon[m - 1][n - 1]);
        
        // Initialization the last column
        for (int i = m - 2; i >= 0; i--) {
            dp[i][n - 1] = Math.max(1, dp[i + 1][n - 1] - dungeon[i][n - 1]);
        }
        
        // Initialization the last row
        for (int i = n - 2; i >= 0; i--) {
            dp[m - 1][i] = Math.max(1, dp[m - 1][i + 1] - dungeon[m - 1][i]);
        }
        
        for (int i = m - 2; i >= 0; i--) {
            for (int j = n - 2; j >= 0; j--) {
                dp[i][j] = Math.max(1, Math.min(dp[i + 1][j], 
                   dp[i][j + 1]) - dungeon[i][j]);
            }
        }
        
        return dp[0][0];
    }
}

Tuesday, September 15, 2015

Leetcode: Strobogrammatic Number III

A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside down).
Write a function to count the total strobogrammatic numbers that exist in the range of low <= num <= high.
For example,
Given low = "50", high = "100", return 3. Because 69, 88, and 96 are three strobogrammatic numbers.
Note:
Because the range might be a large number, the low and high numbers are represented as string.
Understand the problem:
The idea would be very close to the previous problem. So we find all the strobogrammatic numbers between the length of low and high. Note that when the n == low or n == high, we need to compare and make sure the strobogrammatic number we find is within the range.

Code (Java):
public class Solution {
    private int count = 0;
    private Map<Character, Character> map = new HashMap<>();
    
    public int strobogrammaticInRange(String low, String high) {
        if (low == null || low.length() == 0 || high == null || high.length() == 0) {
            return 0;
        }
        
        fillMap();
        
        for (int n = low.length(); n <= high.length(); n++) {
            char[] arr = new char[n];
            getStrobogrammaticNumbers(arr, 0, n - 1, low, high);
        }
        
        return count;
    }
    
    private void getStrobogrammaticNumbers(char[] arr, int start, int end, String low, String high) {
        if (start > end) {
            String s = new String(arr);
            if ((s.length() == 1 || s.charAt(0) != '0') && compare(low, s) && compare(s, high)) {
                count++;
            }
            return;
        }
            
        for (char c : map.keySet()) {
            arr[start] = c;
            arr[end] = map.get(c);
                
            if ((start < end) || (start == end && map.get(c) == c)) {
                getStrobogrammaticNumbers(arr, start + 1, end - 1, low, high);
            }
        }
    }
    
    // Return true if s1 <= s2
    private boolean compare(String s1, String s2) {
        if (s1.length() == s2.length()) {
            if (s1.compareTo(s2) <= 0) {
                return true;
            } else {
                return false;
            }
        }
        
        return true;
    }
    
    private void fillMap() {
        map.put('0', '0');
        map.put('1', '1');
        map.put('8', '8');
        map.put('6', '9');
        map.put('9', '6');
    }
}

Leetcode: Alien Dictionary

There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
For example,
Given the following words in dictionary,
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]
The correct order is: "wertf".
Note:
  1. You may assume all letters are in lowercase.
  2. If the order is invalid, return an empty string.
  3. There may be multiple valid order of letters, return any one of them is fine.
Understand the problem:
The problem can be solved by a topological sorting. First we construct the graph based on the ordering relationship. Then do a topological sorting, which return the correct order. 

Code (Java):
public class Solution {
    public String alienOrder(String[] words) {
        // Step 1: build the graph
        Map<Character, Set<Character>> graph = new HashMap<>();
        for (int i = 0; i < words.length; i++) {
            String curr = words[i];
            for (int j = 0; j < curr.length(); j++) {
                if (!graph.containsKey(curr.charAt(j))) {
                    graph.put(curr.charAt(j), new HashSet<Character>());
                }
            }
            
            if (i > 0) {
                connectGraph(graph, words[i - 1], curr);
            }
        }
        
        // Step 2: toplogical sorting
        StringBuffer sb = new StringBuffer();
        Map<Character, Integer> visited = new HashMap<Character, Integer>();
        
        Iterator it = graph.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry) it.next();
            char vertexId = (char) pair.getKey();
            if (toplogicalSort(vertexId, graph, sb, visited) == false) {
                return "";
            }
        }
        
        return sb.toString();
    }
    
    private void connectGraph(Map<Character, Set<Character>> graph, String prev, String curr) {
        if (prev == null || curr == null) {
            return;
        }
        
        int len = Math.min(prev.length(), curr.length());
        
        for (int i = 0; i < len; i++) {
            char p = prev.charAt(i);
            char q = curr.charAt(i);
            if (p != q) {
                if (!graph.get(p).contains(q)) {
                    graph.get(p).add(q);
                }
                break;
            }
        }
    }
    
    private boolean toplogicalSort(char vertexId, Map<Character, Set<Character>> graph, StringBuffer sb, 
                                   Map<Character, Integer> visited) {
        if (visited.containsKey(vertexId)) {
            // visited
            if (visited.get(vertexId) == -1) {
                return false;
            }
            
            // already in the list
            if (visited.get(vertexId) == 1) {
                return true;
            }
        } else {
            // mark as visited
            visited.put(vertexId, -1);
        }
        
        Set<Character> neighbors = graph.get(vertexId);
        for (char neighbor : neighbors) {
            if (toplogicalSort(neighbor, graph, sb, visited) == false) {
                return false;
            }
        }
        
        sb.insert(0, vertexId);
        visited.put(vertexId, 1);
        
        return true;
    }
}

Update on 4/22/19: Topological sort using BFS
public class Solution {
    /**
     * @param words: a list of words
     * @return: a string which is correct order
     */
    public String alienOrder(String[] words) {
        // Write your code here
        if (words == null || words.length == 0) {
            return "";
        }
        
        // step 1: construct the graph
        //
        Map<Character, List<Character>> adjList = new HashMap<>();
        constructGraph(words, adjList);
        
        int numNodes = adjList.size();
        
        StringBuilder ans = new StringBuilder();
        
        // toplogical sorting
        //
        Map<Character, Integer> indegreeMap = new HashMap<>();
        for (Character node : adjList.keySet()) {
            indegreeMap.put(node, 0);
        }
        
        for (Character node : adjList.keySet()) {
            for (Character neighbor : adjList.get(node)) {
                int indegree = indegreeMap.get(neighbor);
                indegree += 1;
                indegreeMap.put(neighbor, indegree);
            }
        }
        
        Queue<Character> queue = new PriorityQueue<>();
        for (Character node : indegreeMap.keySet()) {
            if (indegreeMap.get(node) == 0) {
                queue.offer(node);
            }
        }
        
        while (!queue.isEmpty()) {
            char curNode = queue.poll();
            ans.append(curNode);
            
            for (char neighbor : adjList.get(curNode)) {
                int indegree = indegreeMap.get(neighbor);
                indegree -= 1;
                indegreeMap.put(neighbor, indegree);
                if (indegree == 0) {
                    queue.offer(neighbor);
                }
            }
        }
        
        if (ans.length() < numNodes) {
            return "";
        }
        
        return ans.toString();
    }
    
    private void constructGraph(String[] words, Map<Character, List<Character>> adjList) {
        // construct nodes
        //
        for (String word : words) {
            for (Character c : word.toCharArray()) {
                adjList.put(c, new ArrayList<>());
            }
        }
        
        // construct edges
        //
        for (int i = 1; i < words.length; i++) {
            String prev = words[i - 1];
            String curr = words[i];
            
            for (int j = 0; j < prev.length() && j < curr.length(); j++) {
                if (prev.charAt(j) != curr.charAt(j)) {
                    adjList.get(prev.charAt(j)).add(curr.charAt(j));
                    break;
                }
            }
        }
    }
}




Monday, September 14, 2015

Leetcode: Wiggle Sort

Given an unsorted array nums, reorder it in-place such that nums[0] <= nums[1] >= nums[2] <= nums[3]....
For example, given nums = [3, 5, 2, 1, 6, 4], one possible answer is [1, 6, 2, 5, 3, 4].

Understand the problem:

A[0] <= A[1] >= A[2] <= A[3] >= A[4] <= A[5]
So we could actually observe that there is pattern that
A[even] <= A[odd],
A[odd] >= A[even].

Therefore we could go through the array and check this condition does not hold, just swap.

Code (Java):
public class Solution {
    public void wiggleSort(int[] nums) {
        if (nums == null || nums.length <= 1) {
            return;
        }
        
        for (int i = 0; i < nums.length - 1; i++) {
            if (i % 2 == 0) {
                if (nums[i] > nums[i + 1]) {
                    swap(nums, i, i + 1);
                }
            } else {
                if (nums[i] < nums[i + 1]) {
                    swap(nums, i, i + 1);
                }
            }
        }
    }
    
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}


Leetcode: Perfect Squares

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.
Understand the problem:
This is a DP problem.

-- Define dp[n + 1], where dp[i] means the least number of perfect square numbers for integer i.
-- Initialization. dp[0] = 0. dp[i] = Integer.MAX_VALUE since we calculate the min number
-- Transit function, dp[i] = min(dp[i], dp[i - j * j]), where j * j <= i
-- Final state: dp[n]

Code (Java):
public class Solution {
    public int numSquares(int n) {
        if (n <= 0) {
            return 0;
        }
        
        int[] dp = new int[n + 1];
        
        for (int i = 1; i <= n; i++) {
            dp[i] = Integer.MAX_VALUE;
            for (int j = 1; j * j <= i; j++) {
                dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
            }
        }
        
        return dp[n];
    }
}

Leetocode: Zigzag Iterator

Given two 1d vectors, implement an iterator to return their elements alternately.
For example, given two 1d vectors:
v1 = [1, 2]
v2 = [3, 4, 5, 6]
By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1, 3, 2, 4, 5, 6].
Follow up: What if you are given k 1d vectors? How well can your code be extended to such cases?

Code (Java):
public class ZigzagIterator {
    private List<Integer> v1;
    private List<Integer> v2;
    private int i;
    private int j;
    private int listId;

    public ZigzagIterator(List<Integer> v1, List<Integer> v2) {
        this.v1 = v1;
        this.v2 = v2;
        this.i = 0;
        this.j = 0;
        this.listId = 0;
    }

    public int next() {
        int result = 0;
        if (i >= v1.size()) {
            result = v2.get(j);
            j++;
        } else if (j >= v2.size()) {
            result = v1.get(i);
            i++;
        } else {
            if (listId == 0) {
                result = v1.get(i);
                i++;
                listId = 1;
            } else {
                result = v2.get(j);
                j++;
                listId = 0;
            }
        }
        
        return result;
    }

    public boolean hasNext() {
        return i < v1.size() || j < v2.size();
    }
}
/** * Your ZigzagIterator object will be instantiated and called as such: * ZigzagIterator i = new ZigzagIterator(v1, v2); * while (i.hasNext()) v[f()] = i.next(); */ Update on 5/14/19:
public class ZigzagIterator {
    /*
    * @param v1: A 1d vector
    * @param v2: A 1d vector
    */
    private Iterator<Integer> it1;
    private Iterator<Integer> it2;
    private int count = 0;
    public ZigzagIterator(List<Integer> v1, List<Integer> v2) {
        // do intialization if necessary
        it1 = v1.iterator();
        it2 = v2.iterator();
        count = 0;
    }

    /*
     * @return: An integer
     */
    public int next() {
        int ans = 0;
        // write your code here
        if (!it1.hasNext()) {
            ans = (Integer)it2.next();
        } else if (!it2.hasNext()) {
            ans = (Integer)it1.next();
        } else if (count == 0) {
            ans = (Integer) it1.next();
            count = 1;
        } else {
            ans = (Integer) it2.next();
            count = 0;
        }

        return ans;
    }

    /*
     * @return: True if has next
     */
    public boolean hasNext() {
        // write your code here
        return it1.hasNext() || it2.hasNext();
    }
}

/**
 * Your ZigzagIterator object will be instantiated and called as such:
 * ZigzagIterator solution = new ZigzagIterator(v1, v2);
 * while (solution.hasNext()) result.add(solution.next());
 * Output result
 */

Tuesday, September 8, 2015

Leetcode: Closest Binary Search Tree Value II

Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.
Note:
  • Given target value is a floating point.
  • You may assume k is always valid, that is: k ≤ total nodes.
  • You are guaranteed to have only one unique set of k values in the BST that are closest to the target.
Follow up:
Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?
Hint:
  1. Consider implement these two helper functions:
    1. getPredecessor(N), which returns the next smaller node to N.
    2. getSuccessor(N), which returns the next larger node to N.
  2. Try to assume that each node has a parent pointer, it makes the problem much easier.
  3. Without parent pointer we just need to keep track of the path from the root to the current node using a stack.
  4. You would need two stacks to track the path in finding predecessor and successor node separately.
Brute-force solution:
The straight-forward solution would be to use a heap. We just treat the BST just as a usual array and do a in-order traverse. Then we compare the current element with the minimum element in the heap, the same as top k problem.

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    private PriorityQueue&lt;Integer&gt; minPQ;
    private int count = 0;
    public List&lt;Integer&gt; closestKValues(TreeNode root, double target, int k) {
        minPQ = new PriorityQueue&lt;Integer&gt;(k);
        List&lt;Integer&gt; result = new ArrayList&lt;Integer&gt;();
        
        inorderTraverse(root, target, k);
        
        // Dump the pq into result list
        for (Integer elem : minPQ) {
            result.add(elem);
        }
        
        return result;
    }
    
    private void inorderTraverse(TreeNode root, double target, int k) {
        if (root == null) {
            return;
        }
        
        inorderTraverse(root.left, target, k);
        
        if (count &lt; k) {
            minPQ.offer(root.val);
        } else {
            if (Math.abs((double) root.val - target) &lt; Math.abs((double) minPQ.peek() - target)) {
                minPQ.poll();
                minPQ.offer(root.val);
            }
        }
        count++;
        
        inorderTraverse(root.right, target, k);
    }
}

Analysis:
The time complexity would be O(k + (n - k) logk). 
Space complexity is O(k).

A time linear solution:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> closestKValues(TreeNode root, double target, int k) {
        List<Integer> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        
        Stack<Integer> precedessor = new Stack<>();
        Stack<Integer> successor = new Stack<>();
        
        getPredecessor(root, target, precedessor);
        getSuccessor(root, target, successor);
        
        for (int i = 0; i < k; i++) {
            if (precedessor.isEmpty()) {
                result.add(successor.pop());
            } else if (successor.isEmpty()) {
                result.add(precedessor.pop());
            } else if (Math.abs((double) precedessor.peek() - target) < Math.abs((double) successor.peek() - target)) {
                result.add(precedessor.pop());
            } else {
                result.add(successor.pop());
            }
        }
        
        return result;
    }
    
    private void getPredecessor(TreeNode root, double target, Stack<Integer> precedessor) {
        if (root == null) {
            return;
        }
        
        getPredecessor(root.left, target, precedessor);
        
        if (root.val > target) {
            return;
        }
        
        precedessor.push(root.val);
        
        getPredecessor(root.right, target, precedessor);
    }
    
    private void getSuccessor(TreeNode root, double target, Stack<Integer> successor) {
        if (root == null) {
            return;
        }
        
        getSuccessor(root.right, target, successor);
        
        if (root.val <= target) {
            return;
        }
        
        successor.push(root.val);
        
        getSuccessor(root.left, target, successor);
    }
}

Update on 4/30/19: Time complexity O(k + logn)
/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */

public class Solution {
    /**
     * @param root: the given BST
     * @param target: the given target
     * @param k: the given k
     * @return: k values in the BST that are closest to the target
     */
    public List<Integer> closestKValues(TreeNode root, double target, int k) {
        // write your code here
        List<Integer> ans = new ArrayList<>();
        if (root == null) {
            return ans;
        }

        // step 1: find the closet value and save the path
        Stack<TreeNode> lowerStack = new Stack<>();
        Stack<TreeNode> upperStack = new Stack<>();

        TreeNode p = root;
        while (p != null) {
            if (p.val < target) {
                lowerStack.push(p);
                p = p.right;
            } else {
                upperStack.push(p);
                p = p.left;
            }
        }

        for (int i = 0; i < k; i++) {
            if (lowerStack.isEmpty()) {
                TreeNode top = upperStack.pop();
                ans.add(top.val);
                goUpperNext(top.right, upperStack);
            
            } else if (upperStack.isEmpty()) {
                TreeNode top = lowerStack.pop();
                ans.add(top.val);
                goLowerNext(top.left, lowerStack);
            } else if (upperStack.peek().val - target <= target - lowerStack.peek().val) {
                TreeNode top = upperStack.pop();
                ans.add(top.val);
                goUpperNext(top.right, upperStack);
            } else if (upperStack.isEmpty() || target - lowerStack.peek().val < upperStack.peek().val - target) {
                TreeNode top = lowerStack.pop();
                ans.add(top.val);
                goLowerNext(top.left, lowerStack);
            }
        }

        return ans;
    }

    private void goUpperNext(TreeNode node, Stack<TreeNode> stack) {
        TreeNode p = node;
        while (p != null) {
            stack.push(p);
            p = p.left;
        }
    }

    private void goLowerNext(TreeNode node, Stack<TreeNode> stack) {
        TreeNode p = node;
        while (p != null) {
            stack.push(p);
            p = p.right;
        }
    }
}

Leetcode: Encode and Decode Strings

Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings.
Machine 1 (sender) has the function:
string encode(vector<string> strs) {
  // ... your code
  return encoded_string;
}
Machine 2 (receiver) has the function:
vector<string> decode(string s) {
  //... your code
  return strs;
}
So Machine 1 does:
string encoded_string = encode(strs);
and Machine 2 does:
vector<string> strs2 = decode(encoded_string);
strs2 in Machine 2 should be the same as strs in Machine 1.
Implement the encode and decode methods.
Note:
  • The string may contain any possible characters out of 256 valid ascii characters. Your algorithm should be generalized enough to work on any possible characters.
  • Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.
  • Do not rely on any library method such as eval or serialize methods. You should implement your own encode/decode algorithm.
Understand the problem:
This is just an implementation problem. The key is how to separate the list of strings during the serialization process so we can decode the string in the de-serialization process.

One way we can think of is to use the number at front. e.g. abcdef, we can store 6abcdef. 
However, what if the string also starts from numbers, e.g. 123abc. In this case, what we stored is 6123abc, which is wrong. Therefore, we need to use another divider to divide the length of the string with the string itself. In this solution, we just use '#'. 

One thing needs to be careful in this such kind problem is the length of the string, which is in the form of string, is not a single character. Therefore, we need to parse the string until we see the divider. 

Code (Java):
public class Codec {

    // Encodes a list of strings to a single string.
    public String encode(List<String> strs) {
        if (strs == null || strs.size() == 0) {
            return "";
        }
        
        StringBuffer sb = new StringBuffer();
        
        for (String str : strs) {
            int len = str == null ? 0 : str.length();
            sb.append(len);
            sb.append('#');
            sb.append(str);
        }
        
        return sb.toString();
    }

    // Decodes a single string to a list of strings.
    public List<String> decode(String s) {
        List<String> result = new ArrayList<String>();
        if (s == null || s.length() == 0) {
            return result;
        }
        
        int i = 0;
        while (i < s.length()) {
            int len = 0;
            // Get length
            while (i < s.length() && s.charAt(i) != '#') {
                len = len * 10 + Character.getNumericValue(s.charAt(i));
                i++;
            }
            
            String str = s.substring(i + 1, i + len + 1);
            result.add(str);
            i = i + len + 1;
        }
        
        return result;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.decode(codec.encode(strs));


Update on 1/27/15:
public class Codec {

    // Encodes a list of strings to a single string.
    public String encode(List<String> strs) {
        if (strs == null || strs.size() == 0) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        
        for (String str : strs) {
            if (str == null || str.length() == 0) {
                sb.append("0#");
            } else {
                sb.append(str.length() + "#" + str);
            }
        }
        
        return sb.toString();
    }

    // Decodes a single string to a list of strings.
    public List<String> decode(String s) {
        List<String> strs = new ArrayList<>();
        
        if (s == null || s.length() == 0) {
            return strs;
        }
        
        int i = 0;
        while (i < s.length()) {
            int j = i;
            while (j < s.length() && Character.isDigit(s.charAt(j))) {
                j++;
            }
            
            int num = Integer.parseInt(s.substring(i, j));
            i = j;
            i++; // skip '#'
            if (num == 0) {
                strs.add("");
            } else {
                strs.add(s.substring(i, i + num));
            }
            
            i += num;
        }
        
        return strs;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.decode(codec.encode(strs));