300. Longest Increasing Subsequence

本文介绍如何解决最长递增子序列(LIS)问题,通过动态规划算法逐步解析示例,展示如何确定子问题并利用之前计算的结果来提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an unsorted array of integers, find the length of longest increasing subsequence.

For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

这是一道动态规划的经典问题。我们拿题中的例子来说事儿,题目要求只要返回LIS的长度即可。(我尽量用数字表示,感觉比较容易理解)。

0. 对于[10],LIS就是1。

1. 对于[10, 9], LIS还是1。因为9比10小所以无法构成上升序列。

2. 对于[10, 9, 2],LIS也还是1,原因同上,无法构成上升序列。

3. 对于[10, 9, 2, 5], 这个时候加入5,惊奇的发现可以有上升序列了,但问题是和谁构成上升序列。这个时候就需要一次比较之前的数字了。10和9都比5大所以只有2能和5构成上升序列。因此截止目前为止,由于数字5的加入,LIS为2([2, 5]).

4. 对于[10, 9, 2, 5, 3],加入3的时候,我们依旧依次比较之前的元素。10和9比3大,不够成IS,2和3构成IS,值为2,5比3大同样不构成上升序列。因此由于数字3的加入,造成了和数字2构成长度为2的上升序列。

5. 对于[10, 9, 2, 5, 3, 7],由于数字7的加入,这下就厉害了。10和9比7大不考虑,2和7构成长度为2的上升序列,5和7构成长度为2 + 1 = 3的上升序列(参见3),3和7构成长度为2 + 1 = 3的上升序列(参见4);

6. 对于[10, 9, 2, 5, 3, 7, 101],依次比较之前的元素,10和101构成长度为2的上升序列,9和101构成长度为2的上升序列,2和101构成长度为2的上升序列,5和101构成长度为3的上升序列,3和101构成长度为3的上升序列,7和101构成长度为4的上升序列(参考5,数字7和之前的数字可构成上升序列)。此时的LIS为4.

7. 对于[10, 9, 2, 5, 3, 7, 101, 18],加入数字18和上一步加入数字101情况是一样的,LIS为数字18和7构成的长度为4的上升序列,由于101比18大,因此它俩不构成上升序列。

走了一遍这个过程,我们发现,每当加入一个新的元素的时候,我们总是需要知道以之前的元素结尾的上升序列长度,并且是逐一比较取最大值。因此对于某一个元素nums[i],他的LIS为:max(1, dp[j] + 1) 此时j < i 且nums[j] < nums[i](等号要看对上升序列的定于)。

这个代码是O(n2)的解法,还有更优解今后再添加。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        //10, 9, 2, 5, 3, 7, 101, 18
        if (nums.size() == 0) return 0;
        vector<int> dp(nums.size(), 1);
        int len = 1;
        for (int i = 0; i < nums.size(); i++) {
            dp[i] = 1;
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i] && dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1;
                }
                len = max(dp[i], len);
            }
        }
        return len;
    }
};


参考资料: 动态规划:从新手到专家

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值