2019年10月28日 星期一

Russian Doll Envelopes


Russian Doll Envelopes

  • Lintcode : 602 / Leetcode : 354
  • Level : Hard

Problem

Give a number of envelopes with widths and heights given as a pair of integers (w, h). One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope.
Find the maximum number of nested layers of envelopes.

Example
Example 1:

Input:[[5,4],[6,4],[6,7],[2,3]]
Output:3
Explanation:
the maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]).
Example 2:

Input:[[4,5],[4,6],[6,7],[2,3],[1,1]]
Output:4
Explanation:
the maximum number of envelopes you can Russian doll is 4 ([1,1] => [2,3] => [4,5] / [4,6] => [6,7]).

Concept & Algorithm

Time Complexity & Space Complexity

First
time : O(n ^ 2)
space: O(n)
Second
time : O( < n ^ 2) (lower_bound will < O(n))
space: O(n)

Answer

/*
bool comparePairs(const pair<int,int>& a, const pair<int,int>& b){
    if (a.first < b.first) return true;
    if (a.first > b.first) return false;
    return a.second < b.second;
}

class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        int n = envelopes.size();
        if (n == 0) return 0;
        vector<int> dp(n, 1);
        int ans = 1;
        sort(envelopes.begin(), envelopes.end());
        for (int i = 0; i < n; i++) {
            for (int j = i - 1; j >= 0; j--) {
                if (envelopes[i].first > envelopes[j].first && envelopes[i].second > envelopes[j].second) {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
            ans = max(ans, dp[i]);
        }
        return ans;
    }

};
*/
bool cmp(const pair<int,int>&x, const pair<int, int>&y) {
  return x.first != y.first ? x.first < y.first : x.second > y.second;
}

class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        int n = envelopes.size();
        if (n == 0) {
            return 0;
        }

        sort(envelopes.begin(), envelopes.end(), cmp);
        vector<int> dp(n), height(n+1, INT_MAX);
        for (int i = 0; i < n; i++) {
            int k = lower_bound(height.begin(), height.end(), envelopes[i].second) - height.begin() ;
            dp[i] = k;
            height[k] = envelopes[i].second;
        }

        int ans = 0;
        for (int i = 0; i < n; i++) {
            ans = max(ans, dp[i]);
        }
        return ans + 1;
    }
};
tags: DP

2019年10月27日 星期日

Longest Increasing Subsequence


Longest Increasing Subsequence

  • Lintcode : 76 / Leetcode : 300
  • Level : Medium

Problem

Given a sequence of integers, find the longest increasing subsequence (LIS).

You code should return the length of the LIS.

Example
Example 1:
    Input:  [5,4,1,2,3]
    Output:  3

    Explanation:
    LIS is [1,2,3]

Example 2:
    Input: [4,2,4,5,3,7]
    Output:  4

    Explanation: 
    LIS is [2,4,5,7]
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.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n ^ 2)
space: O(n)

Answer

class Solution {
public:
    int longestIncreasingSubsequence(vector<int> &nums) {
        int n = nums.size();
        if (n == 0) return 0;
        int ans = 1;
        vector<int> dp(n, 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                    ans = max(ans, dp[i]);
                }
            }
        }
        return ans;
    }
};
tags: DP

Largest Divisible Subset


Largest Divisible Subset

  • Lintcode : 603 / Leetcode : 368
  • Level : Medium

Problem

Given a set of distinct positive integers, find the largest subset such that every pair (Si, Sj) of elements in this subset satisfies: Si % Sj = 0 or Sj % Si = 0.

Example
Example 1:

Input: nums =  [1,2,3], 
Output: [1,2] or [1,3]
Example 2:

Input: nums = [1,2,4,8], 
Output: [1,2,4,8]
Notice
If there are multiple solutions, return any subset is fine.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n ^ 2)
space: O(n ^ 2)

Answer

class Solution {
public:
    vector<int> largestDivisibleSubset(vector<int> &nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> dp(n);
        vector<int> ans;
        for (int i = 0; i < n; i++) {
            int maxLength = 0;
            for (int j = i - 1; j >= 0; j--) {
                if (nums[i] % nums[j] == 0) {
                    int len = dp[j].size();
                    if (len > maxLength) {
                        dp[i] = dp[j];
                        maxLength = len;
                    }
                }
            }
            dp[i].push_back(nums[i]);
            int dpSize = dp[i].size();
            if (dpSize > ans.size()) {
                ans = dp[i];
            }
        }
        return ans;
    }
};
tags: DP

Knight Shortest Path


Knight Shortest Path

  • Lintcode : 611 / Leetcode :
  • Level : Medium

Problem

Given a knight in a chessboard (a binary matrix with 0 as empty and 1 as barrier) with a source position, find the shortest path to a destination position, return the length of the route.
Return -1 if destination cannot be reached.

Example
Example 1:

Input:
[[0,0,0],
 [0,0,0],
 [0,0,0]]
source = [2, 0] destination = [2, 2] 
Output: 2
Explanation:
[2,0]->[0,1]->[2,2]
Example 2:

Input:
[[0,1,0],
 [0,0,1],
 [0,0,0]]
source = [2, 0] destination = [2, 2] 
Output:-1
Clarification
If the knight is at (x, y), he can get to the following positions in one step:

(x + 1, y + 2)
(x + 1, y - 2)
(x - 1, y + 2)
(x - 1, y - 2)
(x + 2, y + 1)
(x + 2, y - 1)
(x - 2, y + 1)
(x - 2, y - 1)
Notice
source and destination must be empty.
Knight can not enter the barrier.
Path length refers to the number of steps the knight takes.

Concept & Algorithm

Time Complexity & Space Complexity

time : worst O(8 ^ step) / best O(8 ^ (step - 1))
space: O(m * n) (n = row, m = column)

Answer

/**
 * Definition for a point.
 * struct Point {
 *     int x;
 *     int y;
 *     Point() : x(0), y(0) {}
 *     Point(int a, int b) : x(a), y(b) {}
 * };
 */
class Solution {
vector<vector<int>> dir = {{1, 2}, {1 , -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, 1}, {-2, -1}};
bool isValid(vector<vector<bool>> &grid, int r, int c) {
    if (r < 0 || c < 0 || r >= grid.size() || c >= grid[0].size() || grid[r][c]) return false;
    return true;
}
public:
    int shortestPath(vector<vector<bool>> &grid, Point &source, Point &destination) {
        if (grid.size() == 0 || grid[0].size() == 0) return -1;
        int n = grid.size(), m = grid[0].size();
        vector<vector<bool>> isVisited(n, vector<bool>(m, false));
        queue<Point> q;
        q.push(source);
        int step = 0;
        isVisited[source.x][source.y] = true;
        while (!q.empty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                Point p = q.front(); q.pop();
                if (p.x == destination.x && p.y == destination.y) return step;
                for(auto d : dir){
                    int row = d[0] + p.x;
                    int col = d[1] + p.y;
                    if (!isValid(grid, row, col) || isVisited[row][col]) continue;
                    q.push(Point(row, col));   
                    isVisited[row][col] = true;
                }
            }
            step++;
        }
        return -1;
    }

};
tags: BFS

2019年10月18日 星期五

Unique Paths II


Unique Paths II

  • Lintcode : 115 / Leetcode : 63
  • Level : Easy

Problem

Follow up for "Unique Paths":

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

Example
Example 1:
    Input: [[0]]
    Output: 1

Example 2:
    Input:  [[0,0,0],[0,1,0],[0,0,0]]
    Output: 2

    Explanation:
    Only 2 different path.


Notice
m and n will be at most 100.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(m n)
space: O(m
n)

Answer

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>> &obstacleGrid) {
        int m = obstacleGrid.size(), n = obstacleGrid[0].size();
        vector<vector<int>> dp(m, vector<int>(n, 0));
        dp[0][0] = 1;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (obstacleGrid[i][j] == 1) {
                    dp[i][j] = 0;
                }else if (i == 0 && j == 0) {
                    continue;
                }else if (i == 0) {
                    dp[i][j] = dp[i][j - 1];
                }else if (j == 0) {
                    dp[i][j] = dp[i - 1][j];
                }else {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
        }
        return dp[m - 1][n - 1];
    }
};
tags: DP

Unique Paths


Unique Paths

  • Lintcode : 114 / Leetcode : 62
  • Level : Easy

Problem

A robot is located at the top-left corner of a m x n grid.

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid.

How many possible unique paths are there?

Example
Example 1:

Input: n = 1, m = 3
Output: 1    
Explanation: Only one path to target position.
Example 2:

Input:  n = 3, m = 3
Output: 6    
Explanation:
    D : Down
    R : Right
    1) DDRR
    2) DRDR
    3) DRRD
    4) RRDD
    5) RDRD
    6) RDDR
Notice
m and n will be at most 100.
The answer is guaranteed to be in the range of 32-bit integers

Concept & Algorithm

Time Complexity & Space Complexity

time : O(m n)
space: O(m
n)

Answer

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 || j == 0) {
                    dp[i][j] = 1;
                    continue;
                }
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];
    }
};
tags: DP

Climbing Stairs


Climbing Stairs

  • Lintcode : 111 / Leetcode : 70
  • Level : Easy

Problem

You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Example
Example 1:
    Input:  n = 3
    Output: 3

    Explanation:
    1) 1, 1, 1
    2) 1, 2
    3) 2, 1
    total 3.

Example 2:
    Input:  n = 1
    Output: 1

    Explanation:  
    only 1 way.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n)
space: O(n)

Answer

class Solution {
public:
    int climbStairs(int n) {
        vector<int> dp(n + 1, 0);
        if (n == 0) return 0;
        if (n == 1) return 1;
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
};
tags: DP

Minimum Path Sum


Minimum Path Sum

  • Lintcode : 110 / Leetcode : 64
  • Level : Easy

Problem

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Example
Example 1:
    Input:  [[1,3,1],[1,5,1],[4,2,1]]
    Output: 7

    Explanation:
    Path is: 1 -> 3 -> 1 -> 1 -> 1

Example 2:
    Input:  [[1,3,2]]
    Output: 6

    Explanation:  
    Path is: 1 -> 3 -> 2

Notice
You can only go right or down in the path..

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n * m)
space: O(1)

Answer

class Solution {
public:
    int minPathSum(vector<vector<int>> &grid) {
        if (grid.size() == 0 || grid[0].size() == 0) return 0;
        int m = grid.size(), n = grid[0].size();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (i == 0 & j == 0) continue;
                if (i == 0) 
                    grid[i][j] += grid[i][j - 1];
                else if (j == 0)
                    grid[i][j] += grid[i - 1][j];
                else 
                    grid[i][j] += min(grid[i][j - 1], grid[i - 1][j]);
            }
        }
        return grid[m - 1][n - 1];
    }
};
tags: DP

2019年10月16日 星期三

Regular Expression Matching


Regular Expression Matching

  • Lintcode : 154 / Leetcode : 10
  • Level : Hard

Problem

Implement regular expression matching with support for '.' and '*'.

'.' Matches any single character.
'*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).

The function prototype should be:

bool isMatch(string s, string p)

isMatch("aa","a") → false

isMatch("aa","aa") → true

isMatch("aaa","aa") → false

isMatch("aa", "a*") → true

isMatch("aa", ".*") → true

isMatch("ab", ".*") → true

isMatch("aab", "c*a*b") → true

Example
Example 1:

Input:"aa","a"
Output:false
Explanation:
unable to match
Example 2:

Input:"aa","a*"
Output:true
Explanation:
'*' can repeat a

Concept & Algorithm

Time Complexity & Space Complexity

time : O()
space: O()

Answer

class Solution {
public:
    bool isMatch(string &s, string &p) {
        int n = s.size(), m = p.size();
        vector<vector<bool>> isVisited(n, vector<bool>(m, false));
        vector<vector<bool>> memo(n, vector<bool>(m, false));
        return dfs(s, p, 0, 0, isVisited, memo);
    }
private:
    bool dfs(string &s, string &p, int sIndex, int pIndex, vector<vector<bool>> &isVisited, vector<vector<bool>> &memo) {
        if (sIndex == s.size() && pIndex == p.size()) return true;
        if (pIndex == p.size()) return false;
        if (sIndex == s.size()) {
            if (p.size() - pIndex == 1 || (p.size() - pIndex) % 2) return false;
            for (int i = pIndex + 1; i < p.size(); i += 2) {
                if (p[i] != '*') return false;
            }
            return true;
        }
        if (isVisited[sIndex][pIndex]) return memo[sIndex][pIndex];
        bool normal = false, left = false, center = false, right = false;
        if (s[sIndex] == p[pIndex] || p[pIndex] == '.') {
            normal = dfs(s, p, sIndex + 1, pIndex + 1, isVisited, memo);
        }
        if (pIndex + 1 < p.size() && p[pIndex + 1] == '*') {
            if (p[pIndex] == s[sIndex] || p[pIndex] == '.') {
                center = dfs(s, p, sIndex, pIndex + 2, isVisited, memo);
                right = dfs(s, p, sIndex + 1, pIndex, isVisited, memo);
            }else {
                left = dfs(s, p, sIndex, pIndex + 2, isVisited, memo);
            }
        }
        isVisited[sIndex][pIndex] = true;
        return memo[sIndex][pIndex] = normal || left || center || right;
    }
};
tags: DP

Word Break II


Word Break II

  • Lintcode : 582 / Leetcode : 140
  • Level : Hard

Problem

Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each word is a valid dictionary word.

Return all such possible sentences.

Example
Example 1:

Input:"lintcode",["de","ding","co","code","lint"]
Output:["lint code", "lint co de"]
Explanation:
insert a space is "lint code",insert two spaces is "lint co de".
Example 2:

Input:"a",[]
Output:[]
Explanation:dict is null.

Concept & Algorithm

Time Complexity & Space Complexity

time :
space:

Answer

class Solution {
public:
    vector<string> wordBreak(string &s, unordered_set<string> &wordDict) {
        unordered_map<string, vector<string>> memo;
        return dfs(s, wordDict, memo);
    }
private:
    vector<string> dfs(string s, unordered_set<string> &wordDict,unordered_map<string, vector<string>> &memo) {
        if (s.empty()) return {""};
        if (memo.find(s) != memo.end()) return memo[s];
        vector<string> res;
        for (int i = 1; i <= s.length(); i++) {
            string temp = s.substr(0, i);
            if (wordDict.find(temp) == wordDict.end()) continue;
            vector<string> coms = dfs(s.substr(i), wordDict, memo);
            for (auto com : coms) {
                if (i == s.length())
                    res.push_back(temp);
                else
                    res.push_back(temp + " " + com);
            }
        }
        memo[s] = res;
        return memo[s];
    }
};
tags: DP

2019年10月15日 星期二

Word Break


Word Break

  • Lintcode : 107 / Leetcode : 139
  • Level : Medium
  • Follow up : Word Break II, Word Break III

Problem

Given a string s and a dictionary of words dict, determine if s can be broken into a space-separated sequence of one or more dictionary words.

Example
Example 1:
    Input:  "lintcode", ["lint", "code"]
    Output:  true

Example 2:
    Input: "a", ["a"]
    Output:  true

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n ^ 2) Worst Case
space: O(n)

Answer

class Solution {
public:
    bool wordBreak(string &s, unordered_set<string> &dict) {
        vector<int> index;
        int n = s.length();
        // corner case
        if (n == 0) return true;
        int maxLength = INT_MIN;
        for (auto i : dict) {
            maxLength = max(maxLength, static_cast<int> (i.length()));
        }
        vector<bool> dp(n, false);
        for (int i = 0; i < n; i++) {
            string str = s.substr(0, i + 1);
            if (dict.find(str) != dict.end()) {
                dp[i] = true;
                index.push_back(i);
            }else {
                for (int j = index.size() - 1; j >= 0; j--) {
                    if (i - index[j] > maxLength) break; 
                    string temp = s.substr(index[j] + 1, i - index[j]);
                    if (dict.find(temp) != dict.end()) {
                        dp[i] = true;
                        index.push_back(i);
                        break;
                    }
                }
            }
        }
        return dp[n - 1];
    }
};
tags: DP

Subarray Product Less than K


Subarray Product Less than K

  • Lintcode : 1075 / Leetcode : 713
  • Level : Medium

Problem

Your are given an array of positive integers nums.

Count and print the number of (contiguous) subarrays where the product of all the elements in the subarray is less than k.

Example
Example 1:
    Input:  nums = [10, 5, 2, 6], k = 100
    Output:  8

    Explanation:
    The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6].
    Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.


Example 2:
    Input: nums = [5,10,2], k = 10
    Output:  2

    Explanation:
    Only [5] and [2].
Notice
0 < nums.length <= 50000.
0 < nums[i] < 1000.
0 <= k < 10^6.

Concept & Algorithm

Time Complexity & Space Complexity

time : O(n)
space: O(1)

Answer

class Solution {
public:
    int numSubarrayProductLessThanK(vector<int> &nums, int k) {
        int n = nums.size();
        if (k <= 1 || n == 0) return 0;
        int count = 0, left = 0, product = 1;
        for (int i = 0;i < n; i++) {
            product = product * nums[i];
            while (product >= k)
                product /= nums[left++];
            count += i - left + 1;
        }
        return count;
    }
};
tags: 2pointers

Last Position of Target

Last Position of Target Lintcode : 458 / Leetcode : 34 Level : Easy Problem Find the last position of a target number in a sorted ...