# [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;
}
};
```