Home LeetCode-300. 最长上升子序列
Post
Cancel

LeetCode-300. 最长上升子序列

关联

LeetCode-673. 最长递增子序列的个数

方法1 DP

思考

$dp[i]$表示前i个元素中,以$num[i]$元素结尾(必选)的最长上升子序列长度,写出下列状态转移方程: \(dp[i]=max(dp[j])+1,\ 0\le j \lt i,\ num[j]<num[i].\)

整体的最长上升子序列数量是:$LIS=max{dp[i]},\ 0\le i \lt n.$

举例

$nums$109253710118
$dp$10000000
$dp$11000000
$dp$11100000
$dp$11120000
$dp$11122344

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {

public:

	int lengthOfLIS(vector<int>& nums){

		int n=nums.size();

		if(n==0) return 0;

		vector<int> dp(n,0);

		for(int i=0;i<n;i++){//求dp[i]

			dp[i]=1;

			for(int j=0;j<i;j++){

				if(nums[j]<nums[i])

					dp[i]=max(dp[i],dp[j]+1);
			}
		}
		return *max_element(dp.begin(),dp.end());
	}
};

复杂度分析

  • 时间复杂度:$O(n^2)$
  • 空间复杂度:$O(n)$

方法2 贪心+二分

思考

我们让新添加进来的末尾元素尽可能的小,让上升的幅度小一些,以便得到更长的子序列。所以这里采用一个数组d来记录长度为length的最长上升子序列的最小末尾元素,初始值为$d[1]=nums[0]$,注意是从1开始。

因为上升子序列要求严格递增,则数组d也是单调递增的,也就是说越长的上升子序列最小末尾元素也就越大。根据数组d的单调性,我们这里查找可以采用二分法,伪代码如下:

遍历$nums$,更新$len$,和数组d,对于$nums[i]$:

① 如果$nums[i]>d[len]$,则$d[++len]=nums[i]$

② 否则在$d[1:len]$中二分查找:第一个比$nums[i]$小的数$d[k]$,同时$d[k+1]=nums[i]$

举例

 084122$nums[i]$①/②
d0    0 
d08   8
d04   4
d0412  12
d0212  2

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
       int n=nums.size();
       if(n==0) return 0;
       int len=1;
       vector<int> d(n+1,0);
       d[len]=nums[0];
       for(int i=1;i<n;i++){//从nums[1]开始遍历nums
           if(nums[i]>d[len]) d[++len]=nums[i];
           else {
               int l=1,r=len,pos=0;
			   //注意d是从d[1]开始的;如果找不到说明所有的数都比nums[i]大,此时更新d[1],所以初始pos设0
               while(l<=r){
                   int mid=((r-l)>>1)+l;
                   if(d[mid]<nums[i]){
                       pos=mid;
                       l=mid+1;
                   }
                   else r=mid-1;
               }
               d[pos+1]=nums[i];
           }
       }
       return len;
    }
};

复杂度分析

  • 时间复杂度:$O(n\log(n))$
  • 空间复杂度:$O(n)$

更多细节参考$LeetCode$官方题解

This post is licensed under CC BY 4.0 by the author.