Tuesday, November 1, 2016

[Leetcode]Sort Characters By Frequency

Given a string, sort it in decreasing order based on the frequency of characters.
Example 1:
Input:
"tree"

Output:
"eert"

Explanation:
'e' appears twice while 'r' and 't' both appear once.
So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer.
Example 2:
Input:
"cccaaa"

Output:
"cccaaa"

Explanation:
Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer.
Note that "cacaca" is incorrect, as the same characters must be together.
Example 3:
Input:
"Aabb"

Output:
"bbAa"

Explanation:
"bbaA" is also a valid answer, but "Aabb" is incorrect.
Note that 'A' and 'a' are treated as two different characters.
Analysis:
The idea is simple: count the frequency of each character, and then sort the characters by frequency and out put the characters. We can use a two dimension array for the easy counting and sorting. 

public String frequencySort(String s) {
        int[][] count = new int[256][2];
        
        for(char c: s.toCharArray()) {
            count[c][0] = c;
            count[c][1]++;
        }
        
        Arrays.sort(count, new Comparator<int[]>() {
           public int compare(int[] a, int[] b) {
               return a[1] == b[1] ? 0 : (a[1] < b[1] ? 1 : -1);
           } 
        });
        
        
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<256; i++) {
            if (count[i][1] > 0) {
                for(int j=0; j<count[i][1]; j++) {
                    sb.append((char)count[i][0]);
                }
            }
        }
        
        return sb.toString();
    }

Sunday, October 23, 2016

[Leetcode] Path Sum III

You are given a binary tree in which each node contains an integer value.
Find the number of paths that sum to a given value.
The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.
Example:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

Return 3. The paths that sum to 8 are:

1.  5 -> 3
2.  5 -> 2 -> 1
3. -3 -> 11
Analysis:
The idea is very simple: Just Preorder visit the tree and for each node, treat it as root and count the number of path which is equal to sum. There should be a better way to remove the duplicate visit?  

    int helper(TreeNode root, int sum, int total) {
        if (root == null)
            return 0;
        else {
            total += root.val;
            int count = sum == total ? 1 : 0;
            count += helper(root.left, sum, total);
            count += helper(root.right, sum, total);
            return count;
        }
    }
    
    public int pathSum(TreeNode root, int sum) {
        if (root == null)
            return 0;
        else {
            int count = helper(root, sum, 0);
            return count + pathSum(root.left, sum) + pathSum(root.right, sum);
        }
    }

[Leetcode] Find All Anagrams in a String

Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
The order of output does not matter.
Example 1:
Input:
s: "cbaebabacd" p: "abc"

Output:
[0, 6]

Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input:
s: "abab" p: "ab"

Output:
[0, 1, 2]

Explanation:
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab".
Analysis:
One intuitive solution is to iterate all the substring of length p.length() and compare whether the substring is an anagram of p by sorting both substring and p and compare. Unfortunately, it will be time out for big data set since the running time would be O(n*n*klog(k) where n is the length of s and k is the length of p.

Think again how we know two strings are the anagram: we can either sort the two string, or we can count each letters of the string and compare whether the count of each letters are equal. So, for s, we first get the count of each letter of the substring of first p.length() characters.Then, whenever move a letter forward one letter,  we just need to change the count by removing 1 count of the first letter and adding 1 count of the last letter. The running time would be O(n+k) since equals function takes constant time. 
    boolean equals(int[] a, int[] b) {
        for(char c = 'a'; c<='z'; c++) {
            if (a[c] != b[c])
                return false;
        }
        return true;
    }
    
    public List<Integer> findAnagrams(String s, String p) {
        int[] pCount = new int[256];
        for(char c: p.toCharArray())
            pCount[c]++;
            
        int[] sCount = new int[256];
        for(int i=0; i<p.length() && i < s.length(); i++)
            sCount[s.charAt(i)]++;
        
        List<Integer> list = new ArrayList<>();
        if (equals(pCount, sCount))
            list.add(0);
        
        for(int i= p.length(); i < s.length(); i++) {
            sCount[s.charAt(i)]++;
            sCount[s.charAt(i-p.length())]--;
            if (equals(pCount, sCount))
                list.add(i-p.length() + 1);
        }
        return list;
    }

Friday, October 21, 2016

[Leetcode] Partition Equal Subset Sum

Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
  1. Each of the array element will not exceed 100.
  2. The array size will not exceed 200.
Example 1:
Input: [1, 5, 11, 5]

Output: true

Explanation: The array can be partitioned as [1, 5, 5] and [11].
Example 2:
Input: [1, 2, 3, 5]

Output: false

Explanation: The array cannot be partitioned into equal sum subsets.
Analysis:
The problem to have the two subset whose sums are equal is the same as the problem to find a subset whose sum is half of the total of the array which is a typical 0,1 knapsack problem: for a given nums[i], if it is included in the subset, then dp[i][j] = dp[i-1][j - nums[i]], otherwise, dp[i][j] = dp[i-1][j]. The dp transition function is  dp[i][j] = dp[i-1][j] || (j >=nums[i-1] && dp[i-1][j-nums[i-1]]). We can also write the dp algorithm with one dimension array:  dp[j] = dp[j] || (j >=nums[i-1] && dp[j-nums[i-1]]); 
Two dimension array:
    public boolean canPartition(int[] nums) {
        int total = 0;
        for(int i = 0; i<nums.length; i++)
            total += nums[i];
            
        if (total %2 != 0)
            return false;
        
        int target= total / 2;
        boolean[][] dp = new boolean[nums.length+1][target+1];
        dp[0][0] = true;
        for(int i=1; i<=nums.length; i++) {
            for(int j=1; j<=target; j++) {
                dp[i][j] = dp[i-1][j] || (j >=nums[i-1] && dp[i-1][j-nums[i-1]]); 
            }
        }
        return dp[nums.length][target];
    }

One dimension array:

public boolean canPartition(int[] nums) {
        int total = 0;
        for(int i = 0; i<nums.length; i++)
            total += nums[i];
            
        if (total %2 != 0)
            return false;
        
        int target= total / 2;
        boolean[] dp = new boolean[target+1];
        dp[0] = true;
        for(int i=1; i<=nums.length; i++) {
            for(int j=target; j >=0 ;j--) {
                dp[j] = dp[j] || (j >=nums[i-1] && dp[j-nums[i-1]]); 
            }
        }
        return dp[target];
    }

Thursday, October 20, 2016

[Leetcode] Pacific Atlantic Water Flow

Given an m x n matrix of non-negative integers representing the height of each unit cell in a continent, the "Pacific ocean" touches the left and top edges of the matrix and the "Atlantic ocean" touches the right and bottom edges.
Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower.
Find the list of grid coordinates where water can flow to both the Pacific and Atlantic ocean.
Note:
  1. The order of returned grid coordinates does not matter.
  2. Both m and n are less than 150.
Example:
Given the following 5x5 matrix:

  Pacific ~   ~   ~   ~   ~ 
       ~  1   2   2   3  (5) *
       ~  3   2   3  (4) (4) *
       ~  2   4  (5)  3   1  *
       ~ (6) (7)  1   4   5  *
       ~ (5)  1   1   2   4  *
          *   *   *   *   * Atlantic

Return:

[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix).
Analysis:
Initially, I was trying to iterate all position, and for each position (i,j) use DFS to see whether it can reach both Atlantic and Pacific but unfortunately it is TLE. For each position, the worst case is to visit all node of the matrix and takes O(m*n) time. So for total m*n node it takes O((m*n)^2).

If we think the problem the other way, if a position (i,j) can reach both Pacific and Atlantic, it mean there must be Pacific position (pi, pj) and Atlantic (ai, ai) which connect to (i, j). In another word, (i, j) must be in the DFS/BFS search path beginning from (pi, pj) and (ai, aj). So, if we can find all the node which can be reached from Pacific edge (row or column is 0) and Atlantic (row or column is maximum), these node are the position where water can flow to both the Pacific and Atlantic ocean.


void dfs(int[][] matrix, boolean[][] visited, int pre, int x, int y) {
        if (x < 0 || x >= matrix.length || y <0 || y >= matrix[0].length || visited[x][y] ||  matrix[x][y] < pre)
            return;
        
        visited[x][y] = true;

        dfs(matrix, visited, matrix[x][y], x-1, y);
        dfs(matrix, visited, matrix[x][y], x+1, y);
        dfs(matrix, visited, matrix[x][y], x, y-1);
        dfs(matrix, visited, matrix[x][y], x, y+1);

    }
    
    public List<int[]> pacificAtlantic(int[][] matrix) {
        List<int[]> list = new ArrayList<>();
        if (matrix.length == 0)
            return list;
        int m = matrix.length; 
        int n = matrix[0].length;
        
        boolean[][] dp1 = new boolean[m][n];
        boolean[][] dp2 = new boolean[m][n];
        for(int i=0; i<m; i++) {
            //Pacific
            dfs(matrix, dp1, Integer.MIN_VALUE, i, 0);
            //Atlantic
            dfs(matrix, dp2, Integer.MIN_VALUE, i, n-1);
        }
        
        for(int i=0; i<n; i++) {
            dfs(matrix, dp1, Integer.MIN_VALUE, 0, i);
            dfs(matrix, dp2, Integer.MIN_VALUE, m-1, i);
        }
    
        for(int i=0; i<m; i++) {
            for(int j=0; j<n; j++) {
                if (dp1[i][j] && dp2[i][j]) {
                    int[] pos = {i,j};
                    list.add(pos);
                }
            }
        }
    
        
        return list;
    }

[Leetcode] Battleships in a Board

Given an 2D board, count how many different battleships are in it. The battleships are represented with 'X's, empty slots are represented with '.'s. You may assume the following rules:
  • You receive a valid board, made of only battleships or empty slots.
  • Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape 1xN (1 row, N columns) or Nx1 (N rows, 1 column), where N can be of any size.
  • At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships.
Example:
X..X
...X
...X
In the above board there are 2 battleships.
Invalid Example:
...X
XXXX
...X
This is not a valid board - as battleships will always have a cell separating between them.
Your algorithm should not modify the value of the board.
Analysis:
At the very first glance, it looks like a BFS/DFS to find the group of connected nodes. But it has the limit that all the battleships have to be in the same row or column. In addition, it has the limit that the board cannot be changed, which means you cannot mark the board as visited or not.

Given that the battleship must be in the same row or column, we can simply check all rows and columns and count it if it is a valid battleship. For each row, we need to collect the number of battleships, which is nothing but the same as finding the number of word separated by space. Notice that you need to check whether the battleship is valid or not by checking whether it has upper or down row battleship connected. Similarly we can get the battleships for the columns, except that for the battleship occupying only one space which has been collected by the row already, so no need to recollected.

Comparing to other solutions, this solution is able to take care of the invalid board as well. 


    int getColCount(char[][] board, int k) {
        int m = board.length;
        int n = board[0].length;
        int i = 0;
        int count = 0;
        while(i < m) {
            while(i < m && board[i][k] == '.')
                i++;

            boolean valid = true;
            int c = 0;
            while(i < m && board[i][k] == 'X') {
                if ((k > 0 && board[i][k-1] == 'X') || (k < n-1 && board[i][k+1] == 'X'))
                    valid = false;
                i++;
                c++;
            }
            //exclude the single node
            if (valid && c > 1)
                count++;
        }
        
        return count;
    }
    
    
    int getRowCount(char[][] board, int k) {
        int m = board.length;
        int n = board[0].length;
        int i = 0;
        int count = 0;
        while(i < n) {
            while(i <n && board[k][i] == '.')
                i++;

            boolean valid = true;
            int c = 0;
            while(i <n && board[k][i] == 'X') {
                if ((k > 0 && board[k-1][i] == 'X') || (k < m-1 && board[k+1][i] == 'X'))
                    valid = false;
                i++;
                c++;
            }
            if (valid && c > 0)
                count++;
        }
        
        return count;
    }
    
    public int countBattleships(char[][] board) {
        int count = 0;
        if (board.length == 0)
            return 0;
            
        for(int i=0; i<board.length; i++)
            count+= getRowCount(board, i);

        for(int i=0; i<board[0].length; i++)
            count+= getColCount(board, i);        
        
        return count;
    }

Wednesday, October 19, 2016

[Leetcode] Longest Repeating Character Replacement

Given a string that consists of only uppercase English letters, you can replace any letter in the string with another letter at most k times. Find the length of a longest substring containing all repeating letters you can get after performing the above operations.
Note:
Both the string's length and k will not exceed 104.
Example 1:
Input:
s = "ABAB", k = 2

Output:
4

Explanation:
Replace the two 'A's with two 'B's or vice versa.
Example 2:
Input:
s = "AABABBA", k = 1

Output:
4

Explanation:
Replace the one 'A' in the middle with 'B' and form "AABBBBA".
The substring "BBBB" has the longest repeating letters, which is 4.
Analysis:
The basic idea is to iterate all substring which could satisfy the condition.  That is, the substring would become repeating character string if k characters were replaced. If we have count of all substring characters, we know that the maximum number of characters to be replaced = the total number of characters - the max number of any single letter. It would takes O (n^2 * k) time.

We can improve the performance. Notice that if substring(i, j) is a repeating character string and substring(i, j+1) is not, then all substring(i, j+n) will not be a repeating character as well. So we have to increase the i to have another repeating character substring. It is actual a slide window and takes O(n*k) time. 

    int getCount(Map<Character, Integer> m, int k) {
        
        int maxVal = 0;
        int total = 0;
        
        for(Character c: m.keySet()) {
            total += m.get(c);
            maxVal = Math.max(maxVal, m.get(c));
        }

        if (total - maxVal > k)
            return -1;
        
        return total;
    }
    public int characterReplacement(String s, int k) {
        int ret = 0;
        int i = 0;
        int j = 0;

        Map<Character, Integer> m = new HashMap<>();
        while(j < s.length()) {
            m.put(s.charAt(j), m.getOrDefault(s.charAt(j), 0) + 1);
            int count = getCount(m, k);
            //if not satisfied, shrink the windows by increasing i
            if (count < 0) {
                while(i < j && count < 0) {
                    m.put(s.charAt(i), m.get(s.charAt(i)) - 1);
                    count = getCount(m, k);
                    i++;
                }
            }
            ret = Math.max(ret, count);
            j++;
        }
        
        return ret;
    }

Tuesday, January 20, 2015

[Leetcode] Find Peak Element

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.
Analysis:
Pretty strait forward. Given num[-1] = num[n] = -∞ and num[i] ≠ num[i+1], if num[0] is greater than num[1], num[0] will be the peak since num[0] > num[1] and num[0] > num[-1]. If not, then num[1] could be the peak if num[1] > num[2], which could be computed in the next loop.  



    int findPeakElement(const vector &num) {
        if (num.size() == 1)
            return 0;
        int peak = 0;
        for(int i=1; i < num.size(); i++)
        {
            if (num[i] < num[peak])
                return i-1;
            else
                peak = i;
        }
        
        return peak;
    }

Monday, January 19, 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.
Analysis:
It is easy to know that at grid P, since " at any point his health point drops to 0 or below, he dies immediately", the remaining health value should be at least 1,  that is, initialHealth + dungeon >= 1, we have initialHealth = max(1, 1 - dungeon[i][j]).  (Notice, at any grid, the initial health should be at least 1 (for example,  test case [1,0,0] require initial health 1 even though it has positive remaining health at grid[0][1] and grid[0][2])
Similarly, to satisfy the initial health of dungeon[i][j], the initial health of dungeon[i-1][j] (or dungeon[i][j-1]) should be at least initialHealth[i-1][j] + dungeon[i-1][j] = initialHealth[i][j], that is, initialHealth[i][j] = initialHealth[i][j] - dungeon[i-1][j]. 
In addition, if grid[i][j] can go both grid[i+1][j] and grid[i][j+1] to P,  we should choose a path with less initial health between grid[i+1][j] and grid[i][j+1] since it require less initial health of grid[i][j].
We can simply code the solution by having the dynamic programming equations. 



         int calculateMinimumHP(vector &dungeon) {
        int m = dungeon.size();
        int n = dungeon[0].size();
        vector minInitHealth(m, vector<int>(n,0));
        for(int i=m-1; i>=0; i--)
        {
            for (int j=n-1; j>=0; j--)
            {
                if (i == m-1 && j == n-1)
                {
                    minInitHealth[i][j] = max(1, 1 - dungeon[i][j]);
                }  
                else if (i == m-1)
                {
                    minInitHealth[i][j] = max(1, minInitHealth[i][j+1] - dungeon[i][j]);
                }  
                else if (j == n-1)
                {
                    minInitHealth[i][j] = max(1, minInitHealth[i+1][j] - dungeon[i][j]);
                }  
                else
                {
                    minInitHealth[i][j] = max(1, min(minInitHealth[i+1][j],minInitHealth[i][j+1]) - dungeon[i][j]);
                }  
            }
        }
        
        return  minInitHealth[0][0];
    }

Sunday, January 18, 2015

[Leetcode] Excel Sheet Column Title

Given a positive integer, return its corresponding column title as appear in an Excel sheet.
For example:
    1 -> A
    2 -> B
    3 -> C
    ...
    26 -> Z
    27 -> AA
    28 -> AB 
Analysis:
Similar to the problem of "Excel Sheet Column Number", we want to represent a number with 26 as base. The code is almost exactly same as converting a decimal number to string, eg: 1234 -> "1234", except that it is 26 base and beginning from 1 rather than 0 (decimal begins from 0 as 0-9). 


    string convertToTitle(int n) {
        string str = "";
        int k = 26;
        while(n > 0)
        {
            str.insert(str.begin(), (n - 1) % k + 'A');
            n = (n - 1) / k;
        }
        
        return str;
    }

[Leetcode] Excel Sheet Column Number

Given a column title as appear in an Excel sheet, return its corresponding column number.
For example:
    A -> 1
    B -> 2
    C -> 3
    ...
    Z -> 26
    AA -> 27
    AB -> 28 

Analysis:

We know a number could be represented as binary, octal, decimal or hexadecimal. So what if we want to represent a number with 26 as base? We could represent 1 as A, 2 as B and Z as 26 which is exactly how an Excel column title works. 

It is pretty strait forward to convert a decimal represented string to a number, eg "123" = 1*100 + 2*10 + 3. Well, it is almost exactly the same for 26 based number as well, as the following code shows. 




    int titleToNumber(string s) {
        int n = 0;
        int k = 26;
        for(int i=0; i < s.size();i++)
        {
            n = n * k + (s[i] - 'A' + 1);
        }
        return n;
    } 

[Leetcode] Factorial Trailing Zeroes

Given an integer n, return the number of trailing zeroes in n!.
Note: Your solution should be in logarithmic time complexity.
Analysis:
As we know, n! = n * (n-1) * (n-2) * ... * 2 * 1. A simple way to get the trailing zeros is to calculate the value of n! and then count the trailing zeros. The problem is that the value of n! is too big to be hold by an integer. Even if we express the  n! using string, its time complexity is O(N), which does not satisfy the "logarithmic time complexity". 
Observed that every pair factor 5 and 2 of the number 1 to n will contribute a trailing zero for n!. Since from 1 to n, the number of  factor 2 is always greater than the factor of 5, the number of factor 5 is the number of trailing zeros. 
So the problem becomes how many of factor 5 among the number 1 to n. We know there are n/5 factor 5 from 1 to n (named 5, 10, 15, ...., floor(n/5) * 5) and there are n/25 extra factor of 5 (named 25, 50, 75, ... , floor(n/25)*25), and n/125 extra factor of 5, and so on. It is not so difficult to implement the code and the following code explains itself. One special case to handle is the k may be exceed the INT_MAX so better to use long to avoid overflow. 
    



    int trailingZeroes(int n) {
        int count = 0;
        long k = 5;
        while(n >= k)
        {
            count+=n/k;
            k*=5;
        }
        return count;
    }

Friday, January 16, 2015

[Leetcode] Majority Element

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist in the array.
Analysis:

An element m appearing more than n/2 times in the array means that the number of elements which is equal to m is greater than the ones which are different than m. So, if we increment the number by 1 for the m and decrement the number by for other different element, the element left which has count greater than 1 will be the majority element m. 

The code is very strait forward if you got the idea. The time complexity is O(n) since only one loop is needed. Pretty awesome, isn't it?



  int majorityElement(vector<int> &num) {
        int count = 0;
        int m;
        for(int i=0; i < num.size();i++)
        {
            if (count == 0)
            {
                m = num[i];
                count++;
            }
            else 
            {
                if (m != num[i])
                {
                    count--;
                }
                else
                {
                    count++;
                }
            }
        }
        return m;
    }

Thursday, January 15, 2015

[Leetcode] Largest Number

Given a list of non negative integers, arrange them such that they form the largest number.
For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.
Note: The result may be very large, so you need to return a string instead of an integer.
Analysis:
An intuitive way to solve the problem is to sort the numbers by some order and then combine the numbers together by descending order.
The question is how should we sort the number? Apparently, it should not be sorted by the integer value. Given two numbers, how do we know which one is "bigger" in term of the combination results is bigger? It is pretty strait forward, just get the two string combinations and compare which one is bigger. For example, [12, 121], since 12121 is greater than 12112, 12121 is the number we want.
The code is pretty strait forward except don't forget to handle the special case of [0, 0], the result should be "0"  rather then "00" as there is no number of "00". 



    static int myComp(int num1, int num2)
    {
        string s1 = to_string(num1) + to_string(num2);
        string s2 = to_string(num2) + to_string(num1);
        return s1 < s2;
    }

    string largestNumber(vector &num) {
        sort(num.begin(), num.end(), myComp);
        //for case [0, 0], if max is 0, then return "0" rather than "00"
        if (num[num.size()-1] == 0)
            return "0";
        string s;
        for(int i=num.size()-1; i>=0; i--)
            s.append(to_string(num[i]));
            
        return s;
    }

Friday, December 5, 2014

[Leetcode] Intersection of Two Linked Lists

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.
Analysis:
The idea is pretty straightforward: count the length of list A and B, and move the longer list few steps from its head so that two list are at the same position to the end of the list. Move both lists toward the end of the lists and whenever they met, the node is the first node the intersection begins.


     ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int l1 = 0;
        ListNode* p1 = headA;
        while(p1 != NULL) {
            l1++;
            p1 = p1->next;
        }
        
        int l2= 0;
        ListNode* p2 = headB;
        while(p2 != NULL) {
            l2++;
            p2 = p2->next;
        }
        
        p1 = headA;
        p2 = headB;
        if (l1 > l2) {
            for(int i=0; i<l1-l2; i++)
                p1 = p1->next;
        }
        else {
            for(int i=0; i<l2-l1; i++)
                p2 = p2->next;            
        }
        
        while(p1 != NULL && p2 != NULL && p1 != p2)
        {
            p1 = p1->next;
            p2 = p2->next;
        }
            
        return p1;
    }

[Leetcode] Find Minimum in Rotated Sorted Array II

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.
Analysis:
Similar to Find Minimum in Rotated Sorted Array, except that you need to take care of duplicate one.


int findMin(vector &num) {
        int b = 0;
        int e = num.size()-1;
        int minVal = num[0];
        while(b <= e)
        {
            int m = (b+e)/2;
            if (num[m] > num[b])
            {
                minVal = min(minVal, num[b]);
                b = m + 1;
            }
            else if (num[m] < num[e])
            {
                minVal = min(minVal, num[m]);
                e = m - 1;
            }
            else if (num[m] == num[e])
            {
                minVal = min(minVal, num[m]);
                e--;
            }
            else if (num[m] == num[b])
            {
                minVal = min(minVal, num[m]);
                b++;
            }
        }
        return minVal;        
    }

Wednesday, November 19, 2014

[Leetcode] Find Minimum in Rotated Sorted Array

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.
Analysis:
Since it is sorted array, binary search may be the hint. Let m be the middle index of array num, if num[0] < num[m], then first part is sorted, the minimum element would be either num[0] or the minimum of the second part, which can be computed recursively. Similarly, if num[m] < num[n], second part is sorted, the minimum element would be either num[m] or the minimum of the first part. 


 int findMin(vector<int> &num) {
        int b = 0;
        int e = num.size() - 1;
        int minValue = INT_MAX;
        while(b <= e) {
            int m = b + (e- b)/2;
            //it is sorted from b to m
            if (num[b] <= num[m]) {
                minValue = min(num[b], minValue);
                b = m + 1;
            }
            else {
                minValue = min(num[m], minValue);
                e = m-1;
            }
        }
        return minValue;
    }

Tuesday, November 18, 2014

[Leetcode] 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.

Analysis:

Apparently, we need to use extra space to store the minimum element of the stack. We can use one stack s to store the pushed element and another stack sMin to store minimum elements appearing so far. Whenever an element x is pushed, if it is less than current minimum (at the top of sMin stack), push x to the sMin; otherwise, the top of the sMin is the minimum and we push it to sMin;



class MinStack {
    stack<int> s;
    stack<int> sMin;
public:
    void push(int x) {
        s.push(x);
        if (sMin.empty() || x < sMin.top())
            sMin.push(x);
        else
            sMin.push(sMin.top());
    }

    void pop() {
        s.pop();
        sMin.pop();
    }

    int top() {
        return s.top();
    }

    int getMin() {
        return sMin.top();
    }
};

However, it could not pass Leetcode oj as Memory Limit Exceeded.  By looking at the solution again, we notice that if x is greater than minimum value, there is no need to push the sMin top value. Just do some special handle when popping the element: if the element is greater than minimum, do not pop sMin.




class MinStack {
    stack<int> s;
    stack<int> sMin;
public:
    void push(int x) {
        s.push(x);
        if (sMin.empty() || x <= sMin.top())
            sMin.push(x);
    }

    void pop() {
        if (s.top() <= sMin.top())
            sMin.pop();
        s.pop();
    }

    int top() {
        return s.top();
    }

    int getMin() {
        return sMin.top();
    }
};

In addition, we notice that if all the pushed elements are the same, there are still spaces wasted. It is possible to have a better solution so that few spaces needed for sMin.

Friday, October 10, 2014

[Leetcode] Add Binary

Given two binary strings, return their sum (also a binary string).
For example,
a = "11"
b = "1"
Return "100".

    string addBinary(string a, string b) {
        string ret;
        int i = a.size() - 1;
        int j = b.size() - 1;
        int carry = 0;
        while(i >= 0 || j >= 0 || carry > 0)
        {
            int da = i < a.size() ? a[i] - '0' : 0;
            int db = j < b.size() ? b[j] - '0': 0;
            //the value
            int d = (da + db + carry) % 2;
            //the carry
            carry = (da + db + carry) / 2;
            ret.insert(ret.begin(),1, d + '0');
            i--;
            j--;
        }
        
        return ret;
    }

[Leetcode] Plus One

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.

vector<int> plusOne(vector<int> &digits) {
        
        int carry = 0;
        vector<int> nums;
        for(int i=digits.size()-1; i >=0; i--)
        {
            int one = i == digits.size()-1 ? 1 : 0;
            int d = (digits[i] + one + carry) % 10;
            carry =  (digits[i] + one + carry) / 10;
            nums.insert(nums.begin(), d);
        }
        //don't forget carry for case {9}
        if (carry > 0)
            nums.insert(nums.begin(), 1);
        
        return nums;
    }