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();
    }
};