# 0300. Longest Increasing Subsequence ###### tags: `Leetcode` `Medium` `Binary Search` `Dynamic Programming` `Greedy` `Longest Increasing Subsequence` Link: https://leetcode.com/problems/longest-increasing-subsequence/ ## 思路 ### Binary Search $O(NlogN)$ $O(N)$ 最佳解的核心是**直接建一个 increasing sequence** 每一个新的元素来,如果比现在的increasing sequence的最大值大,就直接往后加, 否则binary search找应该要替换的元素(第一个比它自己大的元素) 后来重新做这道题的时候原本想要用stack解,遇到peek比现在的值大就pop,然后在过程中记录最大的stack size,后来发现不行,因为如果遇到$[0,1,0,3,2,3]$这样的测资,最长的subsequence应该是$[0,1,2,3]$,但是按这种方法,答案就会变成$[0,2,3]$ 说明**用stack维持单调栈只适合解决找左边/右边的最大/小值,找一个元素,而不是找整个序列** **注意line20要用<,而不是<=** ### DP $O(N^2)$ $O(N)$ 状态定义:照抄问题 **```dp[i] => s[1:i]```里以```s[i]```结尾的最长的递增子序列的长度**。 状态的转移:寻找最优的前驱状态j,将```dp[i]```与```dp[j]```产生联系。 ## Code ### Binary Search $O(NlogN)$ $O(N)$ ```python= class Solution: def lengthOfLIS(self, nums: List[int]) -> int: seq = [] def findPos(num): start, end = 0, len(seq) while start<end: mid = start+(end-start)//2 if seq[mid]<num: start = mid+1 else: end = mid return start for num in nums: if not seq or num > seq[-1]: seq.append(num) else: # find the smallest element in the list that is bigger than num # and then replace it seq[findPos(num)] = num return len(seq) ``` ```java= class Solution { public int lengthOfLIS(int[] nums) { List<Integer> res = new ArrayList<>(); for(int i = 0;i < nums.length;i++){ if(res.size() == 0){ res.add(nums[i]); // len++; } else{ int currMax = res.get(res.size()-1); if(nums[i]>currMax){ res.add(nums[i]); // len++; } else{ int start = 0; int end = res.size(); while(start<end){ int mid = (start+end)/2; if(res.get(mid)<nums[i]){ start = mid+1; } else{ end = mid; } } res.set(start, nums[i]); } } } return res.size(); } } ``` ### DP ```java= class Solution { public int lengthOfLIS(int[] nums) { int n = nums.length; int[] dp = new int[n]; Arrays.fill(dp, 1); int ans = 1; for(int i=0; i<n; i++){ for(int j=0; j<i; j++){ if(nums[j]<nums[i]){ dp[i] = Math.max(dp[i], dp[j]+1); ans = Math.max(ans, dp[i]); } } } return ans; } } ```