Leetcode 300. Longest Increasing Subsequence
https://leetcode.com/problems/longest-increasing-subsequence/
Medium
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 is4
.
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?
- 经典DP。
- 第一种解法DP,定义f[ i ]为i位置时最长增长子序列长度,f[ i ] = max( f[ j ] + 1 ) if nums[ i ] > nums[ j ]。初始时f[ i ] = 1,目标函数为 max( f[ i ] ),注意不是f[ n ]。
- 第二种解法Patience sorting。假设把nums按照堆大小,分成不同堆。每个堆内都是一个增长子序列。定义tails为对应在各种堆大小时(i.e. 不同子序列长度),这些子序列中最小的尾元素。tails可证明是一个增长数组,因为若最小尾元素不增长的话,就不可能有一个更长的增长子序列。所以只要得出tails数组,它的长度就对应最长增长子序列长度。
- 而要得到tails数组,就扫描一遍nums,然后判断需要添加到tails数组,还是更新它:
- if x is larger than all tails, append it, increase the size by 1
- if tails[i-1] < x <= tails[i], update tails[i]
- https://leetcode.com/problems/longest-increasing-subsequence/solution/
- https://leetcode.com/problems/longest-increasing-subsequence/discuss/74824/JavaPython-Binary-search-O(nlogn)-time-with-explanation
- https://en.wikipedia.org/wiki/Patience_sorting
- https://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures/LongestIncreasingSubsequence.pdf
1 class Solution: 2 def lengthOfLIS1(self, nums: List[int]) -> int: 3 if not nums: 4 return 0 5 6 dp = [1] * len(nums) 7 8 for i in range(len(nums)): 9 for j in range(i): 10 if nums[i] > nums[j]: 11 dp[i] = max(dp[i], dp[j] + 1) 12 13 # should be the maximum element of dp 14 return max(dp) 15 16 def lengthOfLIS(self, nums: List[int]) -> int: 17 if not nums: 18 return 0 19 20 tails = [] 21 22 for num in nums: 23 left, right = 0, len(tails) - 1 24 25 # find the first index "left" where tails[left] >= num 26 while left <= right: 27 middle = (left + right) // 2 28 if num <= tails[middle]: 29 right = middle - 1 30 else: 31 left = middle + 1 32 33 # if num is larger than all tails, append it 34 if left == len(tails): 35 tails.append(num) 36 # if tails[left-1] < num <= tails[left], update tails[left] 37 else: 38 tails[left] = num 39 40 return len(tails)