300. Longest Increasing Subsequence
Description
Given an unsorted array of integers, find the length of longest increasing subsequence. (For this question, it’s stricly increasing.)
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
- There may be more than one LIS combination, it is only necessary for you to return the length.
 - our algorithm should run in O(n2) complexity.
 
Follow up:
Could you improve it to O(nlogn) time complexity?
Idea
DP.
1. O(n2)
Consider that dp[i] represents the longest increasing subsequence ending at i. First initiate the array with value 1. Then for every number j less than i:
- If 
dp[j] < dp[i],dp[i] = max(dp[i], dp[j] + 1)(becausedp[i]contributes to LIS) - otherwise, 
dp[i] = dp[i] - Finally, the result is the maximum of array 
dp 
The time complexity is O(n2)
2. O(nlogn)
Consider we maintain a vector dp and dp[i] means the least value for LIS with length (i + 1).
- If current num is greater than any number in 
dp, push it todp - insert current num to the the 
lower_boundindex. 
Notice that dp is actually ordered, an we can search num in O(logn) time. Then the total time complexity is O(nlogn). And the result is the size of dp.
Solution
// O(n^2)
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if (nums.empty()) {
            return 0;
        }
        vector<int> dp(nums.size(), 1);
        for (int i = 1; i < nums.size(); ++i) {
            for (int j = 0; j < i; ++j) {
                if (nums[j] < nums[i]) {
                    dp[i] = max(dp[i], dp[j] + 1);
                }
            }
        }
        int res = 0;
        for (int i = 0; i < nums.size(); ++i) {
            res = max(res, dp[i]);
        }
        return res;
    }
};
//O(nlogn)
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if (nums.empty()) {
            return 0;
        }
        vector<int> result;
        for (size_t i = 0; i < nums.size(); ++i) {
            auto it = lower_bound(result.begin(), result.end(), nums[i]);
            if (it == result.end()) {
                result.push_back(nums[i]);
            } else {
                *it = nums[i];
            }
        }
        return result.size();
    }
};