「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」
最长上升子序列
今天我们来看一道 leetcode的题,最长上升子序列
题目
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的子序列。
Given an integer array nums, return the length of the longest strictly increasing subsequence.
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].
解题思路:
这道题使用一般方法不好解决,在这里我们使用动态规划的方法来求解这道题。
我们先分配一个数组dp, 定义 dp[i]的含义为 nums中医 nums[i]结尾的最长序列长度。
那如何求出dp[i]的值呢?
- 我们定义0 <= j < i,
- 当 nums[i] > nums[j]时, 说明nums[i]为nums[j]的递增数字,则 最长上升子序列的长度为dp[j] +1.
- 当 nums[i] <=nums[j]时,此时不满足序列上升的条件,跳过。
- 遍历j, 循环执行 第 2、3步。每次遇到第2中情况,计算 dp[i] = Math.max(dp[i], dp[j] + 1);
- 循环计算i, 直到遍历完整个nums。计算出dp[i]中最大的值,即是答案。
代码实现
function lengthOfLIS(nums) {
if(nums.length === 0) return 0;
const dp = new Array(nums.length).fill(1);
let max = 1;
for (let i = 0; i < nums.length; i++) {
for (let j = 0; j < i; j++) {
if(nums[i]>nums[j]) {
dp[i] = Math.max(dp[i], dp[j] +1);
}
max = Math.max(max, dp[i]);
}
}
return max;
}
console.log(lengthOfLIS([10, 9, 2, 5, 3, 7, 101, 18]))
好了,这就是我们今天学习的内容。在本次代码实现过程中整个时间复杂度为O(n^2)
, 你能优化代码使时间复杂度降低到 O(nlogn)
吗?