# 300. Longest Increasing Subsequence

[ **300. Longest Increasing Subsequence**](https://leetcode.com/problems/longest-increasing-subsequence/description/)

Given an unsorted array of integers, find the length of longest increasing subsequence.

**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.
* Your algorithm should run in O(n2) complexity.

**Follow up:** Could you improve it to O(n log n) time complexity?

***My Solutions:***

和#674不同的是数字可以不连续。

方法1：用dp的思想，初始化每个元素的最大长度都是1。然后对每个元素来说，从右至左iterate当前元素左边位置的元素。如果排在元素i之前的元素j，比元素i小，更新dp\[i]为dp\[j] + 1 或者dp\[i]。

时间：O(n^2); 空间：O(n)

方法2：维护一个长度为n的table，先把第一个数放入table。从左至右iterate原数组的时候，

* 如果发现当前元素大于table里的现有最大元素，则把元素加入table，table的index更新。
* 如果相等，不做任何举动。
* 如果当前元素小于table里的现有最大元素，则用binary search找到table里、比当前元素大的第一个元素，替换掉。这样可以维持递增数组的元素尽量的小。

e.g. nums = \[2,5,100,3,4,5]

一开始table是【2，5，100】，当遇到3后，换成【2，3，100】，当遇到4后，换成【2，3，4】，遇到5后，table是【2，3，4，5】

时间：O(nlgn); 空间：O(n)

```java
class Solution {
    public int lengthOfLIS(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        
        //方法1
        // int[] dp = new int[nums.length];
        // Arrays.fill(dp, 1);
        
        // int max = 1;
        // for (int i = 1; i < nums.length; i++) {
        //     for (int j = i - 1; j >= 0; j--) {
        //         if (nums[j] < nums[i]) {
        //             dp[i]= Math.max(dp[j] + 1, dp[i]);
        //             max = Math.max(max, dp[i]);
        //         }
        //     }
        // }
        // return max;
        
        //方法2
        int[] table = new int[nums.length];
        int len = 0;
        table[0] = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > table[len]) {
                len++;
                table[len] = nums[i];
            } else if (nums[i] == table[len]) {
                continue;
            } else {
                int index = binarySearch(table, nums[i], len);
                table[index] = nums[i];
            }
        }
        
        return len + 1;
    }
    
    // find the index of the first number that is equal/larger than n
    private int binarySearch(int[] table, int n, int r) {
        int l = 0;
        while (l + 1 < r) {
            int mid = l + (r - l) / 2;
            if (table[mid] < n) l = mid;
            else r = mid;
        }
        if (table[l] >= n) return l;
        else return r;
    }
}
```
