[LeetCode] 300. Longest Increasing Subsequence(最长上升子序列)
-
Difficulty: Medium
-
Related Topics: Binary Search, Dynamic Programming
-
Link: https://leetcode.com/problems/longest-increasing-subsequence/
Description
Given an integer array nums
, return the length of the longest strictly increasing subsequence.
给定整数数组 nums
,返回最长递增子序列的长度。
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]
.
子序列是一个序列,可以由一个数组通过删除 0 或多个元素,不改变剩余元素的顺序产生。例如,[3, 6, 2, 7]
是数组 [0, 3, 1, 6, 2, 2, 7]
的一个子序列。
Examples
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.
Example 2
Input: nums = [0,1,0,3,2,3]
Output: 4
Example 3
Input: nums = [7,7,7,7,7,7,7]
Output: 1
Constraints
1 <= nums.length <= 2500
-1e4 <= nums[i] <= 1e4
Follow up
- Could you come up with the
O(n2)
solution? - Could you improve it to
O(n log(n))
time complexity?
Solution
这题比我想象中要更难,属于那种给了题解也不一定能懂的类型。先给出一种我能看懂的,复杂度 O(N^2) 的解法:
记 dp[i]
表示以 nums[i]
结尾的 LIS 的长度,对于每个 nums[i]
,我们从 j = 0
遍历到 j = i - 1
,如果出现 nums[j] < nums[i]
(说明 nums[j]
可能是以 nums[i]
结尾的 LIS 的其中一个元素),按以下方程更新 dp[i]
:
dp[i] = max(dp[i], dp[j] + 1)
最后,dp
中的最大值即为所求。与常规的动态规划解法不同,此处的结果不一定是 dp
的最后一个元素,因为 LIS 不一定以 nums.last()
结尾。代码如下:
import kotlin.math.max
class Solution {
fun lengthOfLIS(nums: IntArray): Int {
// dp[i] -> 以 nums[i] 结尾的 LIS 的长度
val dp = IntArray(nums.size) { 1 }
for (i in 1..nums.lastIndex) {
for (j in 0 until i) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1)
}
}
}
return dp.max()?:1
}
}
另外还有一个 O(N log N) 的解法,但由于我实在看不懂,到此作罢