Problem
Problem ID: 300
Title: Longest Increasing Subsequence
Difficulty: Medium
Description:
Given an integer array nums, return the length of the longest strictly increasing subsequence.
A subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].
Thoughts
This is an interesting problem that does not have an intuitive solution to it.
Solution
General Idea
The key to solving this problem is observing that:
- The longest increasing subsequence will contain as many small numbers as possible
- We only need to keep track of the last number (largest so far) of when constructing the increasing subsequence
We solve this problem by tracking multiple subsequence in a single vector
- If a number is greater than the last number in the subsequence, we will just append it to the end
- If a number is smaller than the last number, this means a new subsequence can begin
- This new subsequence can continue from all previous number that are small than it
- As all the numbers are increasing (sorted), we can use binary search to find the most element to start the new subsequence to allow the number.
- It is always guaranteed that the last element is part of a valid subsequence
- As we “greedily” add elements into the subsequence, the size of the subsequence is answer eventhough the elements in it might not represent the exact valid subsequence
Implementation
class Solution {
public:
int b_search(vector<int>& nums, int target) {
int l = 0;
int r = nums.size() -1;
while (l < r) {
int m = (l+r)/2;
if (nums[m] >= target) {
r = m;
} else {
l = m+1;
}
}
return r;
}
int lengthOfLIS(vector<int>& nums) {
vector<int> seq;
for (int num : nums) {
cout << endl;
if (seq.empty() || seq.back() < num) {
seq.push_back(num);
continue;
}
auto i = b_search(seq, num);
if (seq[i] == num) continue;
seq[i] = num;
}
return seq.size();
}
};