Loading

[LeetCode] 300. Longest Increasing Subsequence(最长上升子序列)

Description

Given an integer array nums, return the length of the longest strictly increasing subsequence.
给定整数数组 nums,返回最长递增子序列的长度。

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) 的解法,但由于我实在看不懂,到此作罢

posted @ 2020-11-29 10:31  Zhongju.copy()  阅读(79)  评论(0编辑  收藏  举报