---
# System prepended metadata

title: '[LeetCode 300. Longest Increasing Subsequence ](https://leetcode.com/explore/challenge/card/july-leetcoding-challenge-2021/609/week-2-july-8th-july-14th/3808/)'

---

# [LeetCode 300. Longest Increasing Subsequence ](https://leetcode.com/explore/challenge/card/july-leetcoding-challenge-2021/609/week-2-july-8th-july-14th/3808/)
### Daily challenge Jul 9, 2021 (MEDIAN)

>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]`**. 


:::info
**Example 1:**
**Input:** nums = [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.
:::

:::info
**Example 2:**
**Input:** nums = [0,1,0,3,2,3]
**Output:** 4
:::

:::info
**Example 3:**
**Input:** nums = [7,7,7,7,7,7,7]
**Output:** 1
:::


:::warning
**Constraints:**
* 1 <= nums.length <= 2500
* -104 <= nums[i] <= 104
:::

---



### [Approach 1 : Lower_bound](https://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/) :book: 
**`8 ms`** **`O(nlogn)`**
:::danger
這個方法只能夠求出正確的長度，**無法保證**得到的 sequence 是正確的。
:::

How is this approach working ?
1. 假設當前數值為 **`最大`** ，可以直接存入 vector 的最後，因為它必然能使 sequence 加長。
2. 若當前數值並 **`非`** 最大，我們可以假設它可能是另外一個更好的開始。

:arrow_down: Here is a simple example for easily understand :arrow_down: 

>  EXAMPLE : **[1,2,7,8,3,4,5,9,0]**
**1** -> **[1]**
**2** -> **[1,2]**
**7** -> **[1,2,7]**
**8** -> **[1,2,7,8]**
**3** -> **[1,2,3,8]**  // we replaced 7 with 3, since for the longest sequence we need only the last number and 1,2,3 is our new shorter sequence
**4** -> **[1,2,3,4]** // we replaced 8 with 4, since the max len is the same but 4 has more chances for longer sequence
**5** -> **[1,2,3,4,5]**
**9** -> **[1,2,3,4,5,9]**
**0** -> **[0,2,3,4,5,9]** // we replaced 1 with 0, so that it can become a new sequence
>
>In the end, we get **[0,2,3,4,5,9]**, which is not the correct sequence ( it should be **[1,2,3,4,5,9]** ), but the length = 6 is the valid answer.


```cpp=1
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int > LIS;
        
        for(int i=0; i<nums.size(); i++){
            auto it = lower_bound(LIS.begin(), LIS.end(), nums[i]);
            
            if(it == LIS.end()) LIS.push_back(nums[i]);
            else    *it = nums[i];
        }
        
        return LIS.size();
    }
};
```

### Approach 2 : Binary Search ( Patience Sorting ) :book:
:::info
implement Greedy Method
* [wiki](https://en.wikipedia.org/wiki/Patience_sorting) 
* [slide](https://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures/LongestIncreasingSubsequence.pdf) :+1: 
:::

**`8 ms`** **`O(nlogn)`**

與 Approach 1 想法相同，但使用 Binary Search 尋找可替換的位置。

> EXAMPLE : **[4,5,6,3]**
> Initial state -> size = 0 ( Always point to next NULL element. If value is biggest, put it in current[size] )
**4** -> size = 0 ---> current = [4]
**5** -> size = 1 ---> current = [4,5]
**6** -> size = 2 ---> current = [4,5,6]
**3** -> size = 3 ---> current = [3,5,6]


```cpp=1
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        // Binary Search
        int current[nums.size()];
        int size = 0;
        
        for(auto value : nums){
            int left = 0, right = size;
            while(left < right){
                int middle = (left + right) / 2;
                // find current[left] < value <= current[right]
                if(value > current[middle]){
                    left = middle + 1;
                }
                else{
                    right = middle;
                }
            }
            current[left] = value;
            if(left == size)    size++;
        }
        
        return size;
    }
};
```