[路飞]_老白的算法学习笔记06(最长子序列)

256 阅读1分钟

「这是我参与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]的值呢?

  1. 我们定义0 <= j < i,
  2. 当 nums[i] > nums[j]时, 说明nums[i]为nums[j]的递增数字,则 最长上升子序列的长度为dp[j] +1.
  3. 当 nums[i] <=nums[j]时,此时不满足序列上升的条件,跳过。
  4. 遍历j, 循环执行 第 2、3步。每次遇到第2中情况,计算 dp[i] = Math.max(dp[i], dp[j] + 1);
  5. 循环计算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)吗?