求最长上升子序列长度——C++

声明:本文原题主要来自力扣,记录此博客主要是为自己学习总结,不做任何商业等活动!

一、下面是原题描述

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

 
示例 1:

输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
示例 2:

输入:nums = [0,1,0,3,2,3]
输出:4
示例 3:

输入:nums = [7,7,7,7,7,7,7]
输出:1

1.1题目分析

拿道题目,第一思路是先分析。

求数组最长上升子序列,也就是意味着要遍历整个数组中所有子序列,这时可以考虑是否可以用动态规划。由于动态规划知识,知道这是一题线性动态规划的题目,可以采用线性动态规划解法,即使经典的LIS(Longest Increasing Subsequence)。

动态规划满足三个条件:状态方程、状态转移方程、边界条件,根据分析可知该题满足条件,下面是分析的动态转移方程:

nums = [10, 9, 2, 5, 3, 7, 101, 18]
f(i) = max(f(j)) + 1, 0 <= i <= n, 0 <= j < i - 1; 满足条件nums[i] > nums[j];
i = 0, f(0) = 0;
i = 1, f(1) = 1;
i = 2, f(2) = max(f(1)) + 1;
i = n, f(n) = max(f(j)) + 1; 满足条件nums[i] > nums[j];

子序列个数n 1 2 3 4 5 6 7 8
元素值 10 9 2 5 3 7 101 18
LIS 1 1 1 2 2 3 4 4

1.2代码实现分析

由上面的状态转移方程和表格可知,需要求有n个子序列长度的LIS,就必须先求出第0个,然后退出第1个LIS,一直到该子序列最大长度。假如满足条件nums[i]>nums[j],每一个都在前面的基础上递加1.即关键实现代码如下:

for (int i = 0; i < size; ++i) // 遍历i个个数的子序列
{
    dp[i] = 1;
    for (int j = 0; j < i; ++j) // 求每个子序列的LIS
        if (nums[i] > nums[j])
            dp[i] = std::max(dp[i], dp[j] + 1); // 这里是关键,每次返回最大值
}

1.3完整代码

class Solution {
    /*
    nums = [10,9,2,5,3,7,101,18]
    f(i) = max(f(j)) + 1 , 0 <= i <= n, 0 <= j < i - 1;满足条件nums[i]>nums[j];
    i=0,f(0)=0;
    i=1, f(1)=1;
    i=2, f(2)=max(f(1))+1;
    i=n, f(n)=max(f(j))+1;满足条件nums[i]>nums[j];
    */
public:
    int lengthOfLIS(vector& nums) {
        int size = nums.size();
        if (!size) // 异常判断
            return 0;
        vector dp(size, 0); // 存储n个个数分别为1—n的子序列的LIS

        for (int i = 0; i < size; ++i) // 遍历i个个数的子序列
        {
            dp[i] = 1;
            for (int j = 0; j < i; ++j) // 求每个子序列的LIS
                if (nums[i] > nums[j])
                    dp[i] = std::max(dp[i], dp[j] + 1); // 这里是关键,每次返回最大值
        }
        return *std::max_element(dp.begin(), dp.end()); // 返回最大值
    }
};

1.4结果

求最长上升子序列长度——C++_第1张图片

1.5复杂度分析

由上面代码实现可知,经过了双层遍历,即时间复杂度为O(n^2);申请了n个长度的数组空间,故空间复杂度为O(n)。

你可能感兴趣的:(C++刷题,动态规划,C++,上升,递增,子序列)