Showing posts with label lintcode. Show all posts
Showing posts with label lintcode. Show all posts

Thursday, August 20, 2015

Day 120, Longest Increasing Subsequence, Longest Common Substring Show result, Longest Increasing Continuous subsequence II

Longest Increasing Subsequence


Given a sequence of integers, find the longest increasing subsequence (LIS).
You code should return the length of the LIS.
Have you met this question in a real interview?
Yes
Example
For [5, 4, 1, 2, 3], the LIS  is [1, 2, 3], return 3
For [4, 2, 4, 5, 3, 7], the LIS is [4, 4, 5, 7], return 4
Challenge
Time complexity O(n^2) or O(nlogn)
Clarification
What's the definition of longest increasing subsequence?
    * The longest increasing subsequence problem is to find a subsequence of a given sequence in which the subsequence's elements are in sorted order, lowest to highest, and in which the subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique.  
    * https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
---------------------------------------------------------------------
O(n^2)
class Solution {
public:
    /**
     * @param nums: The integer array
     * @return: The length of LIS (longest increasing subsequence)
     */
    int longestIncreasingSubsequence(vector<int> nums) {
        // write your code here
        if (nums.size() == 0) return 0;
        vector<int> dp(nums.size(),1);
        int longest = 0;
        for (int i = 0; i < nums.size(); i++) {
            for (int j = 0; j < i; j++) {
                if (nums[j] <= nums[i]) {
                    dp[i] = max(dp[i],dp[j] + 1);
                }
                longest = max(longest,dp[i]);
            }
        }
        
        return longest;
    }
};

geeksforgeeks,O(n lg n)

Longest Common Substring Show result 
Given two strings, find the longest common substring.
Return the length of it.
Have you met this question in a real interview? 
Yes
Example
Given A = "ABCD", B = "CBCE", return 2.
Note
The characters in substring should occur continuously in original string. This is different with subsequence.

Challenge
O(n x m) time and memory.
---------------------------------------------------
画个2d矩阵就明白了
class Solution {
public:    
    /**
     * @param A, B: Two string.
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string &A, string &B) {
        // write your code here
        int m = A.length(), n = B.length();
        vector<vector<int> > dp(m + 1,vector<int>(n + 1,0));
        int longest = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (A[i - 1] == B[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    longest = max(longest,dp[i][j]);
                }
            }
        }
        
        return longest;
    }
};

线性额外空间
class Solution {
public:    
    /**
     * @param A, B: Two string.
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string &A, string &B) {
        // write your code here
        int m = A.length(), n = B.length();
        vector<int> dp(n + 1,0);
        int longest = 0;
        for (int i = 1; i <= m; i++) {
            for (int j = n; j >= 1; j--) {
                if (A[i - 1] == B[j - 1]) {
                    dp[j] = dp[j - 1] + 1;
                    longest = max(longest,dp[j]);
                }else {
                    dp[j] = 0;
                }
            }
        }
        
        return longest;
    }
};

Longest Increasing Continuous subsequence II
Give you an integer matrix (with row size n, column size m),find the longest increasing continuous subsequence in this matrix. (The definition of the longest increasing continuous subsequence here can start at any row or column and go up/down/right/left any direction).
Have you met this question in a real interview? 
Yes
Example
Given a matrix:
[
  [1 ,2 ,3 ,4 ,5],
  [16,17,24,23,6],
  [15,18,25,22,7],
  [14,19,20,21,8],
  [13,12,11,10,9]
]
return 25

Challenge
O(nm) time and memory.
--------------------------------------------------
以每一点为path的起始,它所得到最长递增数列都是恒定的
所以用memoization即可
class Solution {
public:
    /**
     * @param A an integer matrix
     * @return  an integer
     */
    int dfs(vector<vector<int>>& A,vector<vector<int>> &dp,int row,int col) {
        if (dp[row][col] != 0) return dp[row][col];

        if (row + 1 < A.size() && A[row + 1][col] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row + 1,col));
        }
        if (row - 1 >= 0 && A[row - 1][col] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row - 1,col));
        }
        if (col - 1 >= 0 && A[row][col - 1] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row,col - 1));
        }
        if (col + 1 < A[0].size() && A[row][col + 1] > A[row][col]) {
            dp[row][col] = max(dp[row][col],dfs(A,dp,row,col + 1));
        }
        
        dp[row][col]++;
        return dp[row][col];
    }
     
    int longestIncreasingContinuousSubsequenceII(vector<vector<int>>& A) {
        // Write your code here
        if (A.size() == 0) return 0;
        int m = A.size(), n = A[0].size();
        vector<vector<int>> dp(m,vector<int>(n,0));
        int longest = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (dp[i][j] == 0) {
                    dp[i][j] = dfs(A,dp,i,j);
                }
                longest = max(longest,dp[i][j]);
            }
        }
        
        return longest;
    }
};

遍历,所有点按高度排序
struct Dot {
        int row;
        int col;
        int height;
        Dot(int x,int y,int h):row(x),col(y),height(h) {
        }
    };

class Solution {
public:
    static bool cmp(const Dot &d1,const Dot &d2) {
        return d1.height < d2.height;
    }

    /**
     * @param A an integer matrix
     * @return  an integer
     */
    int longestIncreasingContinuousSubsequenceII(vector<vector<int>>& A) {
        // Write your code here
        if (A.size() == 0) return 0;
        int m = A.size(), n = A[0].size();
        vector<vector<int>> len(m,vector<int>(n,0));
        vector<Dot> dots;
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                Dot d(i,j,A[i][j]);
                dots.push_back(d);
            }
        }
        
        sort(dots.begin(),dots.end(),cmp);
        int longest = 0;
        for (int i = 0; i < dots.size(); i++) {
            if (dots[i].row + 1 < m && A[dots[i].row + 1][dots[i].col] > dots[i].height
                && len[dots[i].row + 1][dots[i].col] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row + 1][dots[i].col] = len[dots[i].row][dots[i].col] + 1;
            }
            
            if (dots[i].col + 1 < n && A[dots[i].row][dots[i].col + 1] > dots[i].height
                && len[dots[i].row][dots[i].col + 1] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row][dots[i].col + 1] = len[dots[i].row][dots[i].col] + 1;
            }
            
            if (dots[i].row - 1 >= 0 && A[dots[i].row - 1][dots[i].col] > dots[i].height
                && len[dots[i].row - 1][dots[i].col] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row - 1][dots[i].col] = len[dots[i].row][dots[i].col] + 1;
            }
            
            if (dots[i].col - 1 >= 0 && A[dots[i].row][dots[i].col - 1] > dots[i].height
                && len[dots[i].row][dots[i].col - 1] < len[dots[i].row][dots[i].col] + 1) {
                len[dots[i].row][dots[i].col - 1] = len[dots[i].row][dots[i].col] + 1;
            }
        }
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                longest = max(longest,len[i][j]);
            }
        }
        
        return longest + 1;
    }
};

Thursday, July 23, 2015

Day 118, 240 Search a 2D Matrix II, Majority Number III

Search a 2D Matrix II
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
  • Integers in each row are sorted in ascending from left to right.
  • Integers in each column are sorted in ascending from top to bottom.
For example,
Consider the following matrix:
[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]
Given target = 5, return true.
Given target = 20, return false.

---------------------------------------------------------------------------
REFhttp://articles.leetcode.com/2010/10/searching-2d-sorted-matrix-part-ii.html
O(n)
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        int n = matrix[0].size();
        
        int row = 0, col = n - 1;
        while (row < m && col >= 0) {
            if (matrix[row][col] == target) return true;
            if (matrix[row][col] > target) {
                col--;
            }else {
                row++;
            }
        }
        
        return false;
    }
};

O((lgn)^2)
class Solution {
public:
    bool helper(vector<vector<int>>& matrix, int target,int rowStart,int rowEnd,int colStart,int colEnd) {
        if (rowStart > rowEnd || colStart > colEnd) {
            return false;
        }
        
        int row = (rowStart + rowEnd) / 2;
        int left = colStart,right = colEnd;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (matrix[row][mid] == target) return true;
            if (matrix[row][mid] < target) {
                left = mid + 1;
            }else {
                right = mid - 1;
            }
        }
        
        return helper(matrix,target,rowStart,row - 1,right + 1,colEnd) 
                || helper(matrix,target,row + 1,rowEnd,colStart,right);
    }

    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (m == 0) return false;
        int n = matrix[0].size();
        
        return helper(matrix,target,0,m - 1,0,n - 1);
    }
};

Majority Number III
Given an array of integers and a number k, the majority number is the number that occurs more than 1/k of the size of the array.
Find it.
Have you met this question in a real interview? 
Yes
Example
Given [3,1,2,3,2,3,3,4,4,4] and k=3, return 3.
Note
There is only one majority number in the array.

Challenge
O(n) time and O(k) extra space
-------------------------------------------
用hash map来记录value跟count, 原理跟1、2相同
class Solution {
public:
    /**
     * @param nums: A list of integers
     * @param k: As described
     * @return: The majority number
     */
    int majorityNumber(vector<int> nums, int k) {
        // write your code here
        unordered_map<int,int> dic;
        
        for (int i = 0; i < nums.size(); i++) {
            if (dic.find(nums[i]) == dic.end()) {
                dic.insert(make_pair(nums[i],1));
            }else {
                dic[nums[i]]++;
            }
            
            if (dic.size() == k) {
             vector<int> t;
             for (auto kv : dic) {
              t.push_back(kv.first);
             }
             
                for (int i : t) {
                    dic[i]--;
                    if (dic[i] == 0) {
                        dic.erase(i);
                    }
                }
            }
        }
        
        unordered_map<int,int> left;
        int maxCount = 0, maxVal = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (dic.find(nums[i]) != dic.end()) {
                if (left.find(nums[i]) == left.end()) {
                    left[nums[i]] = 1;
                }else {
                    left[nums[i]]++;
                }
                if (maxCount < left[nums[i]]) {
                    maxCount = left[nums[i]];
                    maxVal = nums[i];
                }
            }
        }
        
        return maxVal;
    }
};

Thursday, July 2, 2015

Day 114, Lintcode, #395, Coins in a Line II

Coins in a Line II
There are n coins with different value in a line. Two players take turns to take one or two coins from left side until there are no more coins left. The player who take the coins with the most value wins.
Could you please decide the first player will win or lose?
-----------------------------------------------------
方法一
coins表示在i点的最大利益
getTwo表示在i点最大利益是否要取2个coin
class Solution {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        // write your code here
        int m = values.size();
        if (m < 3) return true;
        
        vector<int> coins(m + 2,0);
        vector<bool> getTwo(m,true);
        
        coins[m - 1] = values[m - 1];
        coins[m - 2] = values[m - 1] + values[m - 2];
        
        for (int i = m - 3; i >= 0; i--) {
            int takeOne = 0, takeTwo = 0;
            // take one
            if (getTwo[i + 1]) {
                takeOne = coins[i + 3] + values[i];
            }else {
                takeOne = coins[i + 2] + values[i];
            }
            
            // take two
            if(getTwo[i + 2]) {
                takeTwo = coins[i + 4] + values[i] + values[i + 1];
            }else {
                takeTwo = coins[i + 3] + values[i] + values[i + 1];
            }
            
            coins[i] = max(takeOne,takeTwo);
            if (takeOne > takeTwo) {
                getTwo[i] = false;
            }
        }
        
        if (getTwo[0]) {
            return coins[0] > coins[2];
        }
        return coins[0] > coins[1];
    }
};

方法二 http://techinpad.blogspot.com/2015/05/lintcode-coins-in-line-ii.html
方法三 http://www.meetqun.com/thread-9798-1-1.html

Sunday, February 1, 2015

Day 99, ##, Fraction to Recurring Decimal, Majority Element, Majority Number II

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)".
---------------------------------------------
Map 里面记录是某一个数的开始的index
reference
注意正负号跟溢出,casting long long
27行,先存map,再乘10
class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) return "0";
        string rt = "";
        
        if ((numerator < 0 && denominator > 0) || (numerator > 0 && denominator < 0)) {
            rt = "-";
        }
        
        long long dividend = abs((long long)numerator);
        long long divisor = abs((long long)denominator);
        rt += to_string(dividend / divisor);
        
        dividend %= divisor;
        if (dividend == 0) return rt;
        
        rt += '.';
        unordered_map<int,int> mapping;
        
        while (dividend != 0) {
            if (mapping.find(dividend) != mapping.end()) {
                rt.insert(mapping[dividend],"(");
                rt += ")";
                return rt;
            }
            mapping[dividend] = rt.size();
            dividend *= 10;
            rt += to_string(dividend / divisor);
            dividend %= divisor;
        }

        return rt;
    }
};

In Java, updated on Feb-13th-2019
class Solution {
    public String fractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) return "0";
        StringBuilder sb = new StringBuilder();
        
        if ((numerator < 0 && denominator > 0) || (numerator > 0 && denominator < 0)) {
            sb.append("-");
        }
        
        long num = Math.abs((long)numerator);
        long den = Math.abs((long)denominator);
        
        sb.append(num / den);
        num %= den;
        if (num == 0) return sb.toString();
        sb.append(".");
        
        Map<Long, Integer> map = new HashMap<>();
        map.put(num, sb.length());
        
        while (num > 0) {
            num *= 10;
            sb.append(num / den);
            num %= den;
            if (map.containsKey(num)) {
                sb.insert(map.get(num),"(");
                sb.append(")");
                return sb.toString();
            }
            
            map.put(num, sb.length());
        }
        
        return sb.toString();
    }
}

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.
-----------------------------------------------------
fact: we are given an array with a majority element in it.
每次都丢掉2个不同数,majority最后肯定会被留下来
class Solution {
public:
    int majorityElement(vector<int> &num) {
        int count = 1;
        int countElem = num[0];
        
        for (int i = 1; i < num.size(); i++) {
            if (count == 0) {
                countElem = num[i];
                count++;
                continue;
            }
            if (countElem == num[i]) {
                count++;
            }else {
                count--;
            }
            
        }
        
        return countElem;
    }
};

Majority Number II 

Given an array of integers, the majority number is the number that occurs more than 1/3 of the size of the array.
Find it.
Note
There is only one majority number in the array
Example
For [1, 2, 1, 2, 1, 3, 3] return 1
-------------------------------------
每次都丢掉3个不同的数,最后超过1/3的肯定会被留下来
最后还要重新对留下来的2个数重新计数,因为超1/3的数可能会被过度消耗
举例:1,1,1,1,2,2,3,3,4,4,4
class Solution {
public:
    /**
     * @param nums: A list of integers
     * @return: The majority number occurs more than 1/3.
     */
    int majorityNumber(vector<int> nums) {
        // write your code here
        int count_1 = 1, count_2 = 0;
        int cand_1 = nums[0], cand_2;
        
        for (int i = 1; i < nums.size(); i++) {
            if (count_1 == 0 && cand_2 != nums[i]) {
                count_1 = 1;
                cand_1 = nums[i];
                continue;
            }
            if (count_2 == 0 && cand_1 != nums[i]) {
                count_2 = 1;
                cand_2 = nums[i];
                continue;
            }
            
            if (nums[i] != cand_1 && nums[i] != cand_2) {
                count_1--;
                count_2--;
            }
            
            if (nums[i] == cand_1) {
                count_1++;
            }
            if (nums[i] == cand_2) {
                count_2++;
            }
        }
        
        count_1 = 0;
        count_2 = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] == cand_1) count_1++;
            if (nums[i] == cand_2) count_2++;
        }
        
        if (count_1 > count_2) {
            return cand_1;
        }else {
            return cand_2;
        }
    }
};


Wednesday, January 28, 2015

Day 96, ##, Topological Sorting

Topological Sorting 

Given an directed graph, a topological order of the graph nodes is defined as follow:
  • For each directed edge A-->B in graph, A must before B in the order list.
  • The first node in the order can be any node in the graph with no nodes direct to it.
Find any topological order for the given graph.
Note
You can assume that there is at least one topological order in the graph.
Example
For graph as follow:

The topological order can be:
[0, 1, 2, 3, 4, 5]
or
[0, 2, 3, 1, 5, 4]
or
....

Challenge
Can you do it in both BFS and DFS?
----------------------------------------------------------------------------
 DFS
/**
 * Definition for Directed graph.
 * struct DirectedGraphNode {
 *     int label;
 *     vector<DirectedGraphNode *> neighbors;
 *     DirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    /**
     * @param graph: A list of Directed graph node
     * @return: Any topological order for the given graph.
     */
     
    void dfs(DirectedGraphNode * node, vector<DirectedGraphNode*> &rt,unordered_set<DirectedGraphNode*> &visit) {
        visit.insert(node);
        for (int i = 0; i < node->neighbors.size(); i++) {
            if (visit.find(node->neighbors[i]) == visit.end()) {
                dfs(node->neighbors[i], rt, visit);
            }
        }
        
        rt.push_back(node);
    }
     
    vector<DirectedGraphNode*> topSort(vector<DirectedGraphNode*> graph) {
        // write your code here
        vector<DirectedGraphNode*> rt;
        unordered_set<DirectedGraphNode*> visit;
        
        for (int i = 0; i < graph.size(); i++) {
            if (visit.find(graph[i]) == visit.end()) {
                dfs(graph[i],rt,visit);
            }
        }
        
        reverse(rt.begin(),rt.end());
        return rt;
    }
};


Wednesday, January 22, 2014

## other: Longest common subsequence

http://lintcode.com/en/problem/longest-common-subsequence/
Let the input sequences be X[0..m-1] and Y[0..n-1] of lengths m and n respectively. And let L(X[0..m-1], Y[0..n-1]) be the length of LCS of the two sequences X and Y. Following is the recursive definition of L(X[0..m-1], Y[0..n-1]).

If last characters of both sequences match (or X[m-1] == Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = 1 + L(X[0..m-2], Y[0..n-2])

If last characters of both sequences do not match (or X[m-1] != Y[n-1]) then
L(X[0..m-1], Y[0..n-1]) = MAX ( L(X[0..m-2], Y[0..n-1]), L(X[0..m-1], Y[0..n-2])

--------------------------
print the length of the longest common sub-sequence
DP
The actual sequence can be generated by using backtrack.
Reference:
http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
int lcs (string a, string b) {
    int m = a.length();
    int n = b.length();
    vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));
    
    for (int i = 1; i < m + 1; i++) {
        for (int j = 1; j < n + 1; j++) {
            if (a[i] == b[i]) {
                dp[i][j] = 1 + dp[i - 1][j - 1];
            }else {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }
    return dp[m][n];
} 
-------------------------------------------------
Recursion

int lcs( char *X, char *Y, int m, int n )
{
   if (m == 0 || n == 0)
     return 0;
   if (X[m-1] == Y[n-1])
     return 1 + lcs(X, Y, m-1, n-1);
   else
     return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));
}