LeetCode 算法:长递增子序列 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 <= nums.length <= 2500
-104 <= nums[i] <= 104

进阶:

你能将算法的时间复杂度降低到 O(n log(n)) 吗?

动态规划

  • 动态规划(Dynamic Programming,简称DP)是一种通过把原问题分解为相对简单的子问题的方式来求解复杂问题的方法。它通常用于优化问题,特别是那些具有重叠子问题和最优子结构的问题。动态规划通常用于计算科学、管理科学、经济学、生物信息学等领域。

  • 动态规划的关键步骤包括:

    1. 定义状态:确定问题的状态,这些状态通常与问题的时间或空间维度相关。

    2. 确定状态转移方程:找出状态之间的关系,即如何从一个状态转移到另一个状态。

    3. 确定边界条件:定义问题的基本情况,也就是动态规划的起点。

    4. 计算顺序:确定计算状态的顺序,以确保在计算当前状态之前,所有依赖的状态都已经被计算。

    5. 实现算法:编写代码实现上述步骤。

  • 动态规划的常见应用包括:

    • 斐波那契数列
    • 背包问题
    • 最长公共子序列(LCS)
    • 最长递增子序列(LIS)
    • 矩阵链乘问题
    • 硬币找零问题
    • 编辑距离问题
  • 动态规划与贪心算法不同,贪心算法在每一步都做出局部最优的选择,而动态规划则通过考虑所有可能的状态来找到全局最优解。

题解

  1. 解题思路:

LeetCode 上的“长递增子序列”问题通常指的是找出一个序列中最长的严格递增子序列(子序列中的元素不一定是连续的)。这个问题可以通过动态规划来解决。下面是一个解题思路:

  1. 定义状态:定义一个数组 dp,其中 dp[i] 表示以第 i 个元素结尾的最长递增子序列的长度。

  2. 初始化:由于每个元素至少可以单独构成一个长度为1的递增子序列,所以 dp 数组的初始值可以设为 1

  3. 状态转移方程:对于每个元素 nums[i],遍历它之前的所有元素 nums[j](其中 j < i),如果 nums[j] < nums[i],则说明 nums[i] 可以接在 nums[j] 后面形成一个更长的递增子序列。这时,更新
    dp[i] 的值为 max(dp[i], dp[j] + 1)

  4. 遍历更新:遍历数组,对于每个元素,根据状态转移方程更新 dp 数组。

  5. 得到结果:遍历结束后,dp 数组中的最大值即为整个数组的最长递增子序列的长度。

  6. 复杂度分析:时间复杂度为 O(n^2),其中 n 是数组 nums 的长度,因为需要两层循环遍历数组。

  1. c++ demo:
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int lengthOfLIS(vector<int>& nums) {
    if (nums.empty()) return 0;
    vector<int> dp(nums.size(), 1); // 初始化dp数组,每个元素至少可以构成长度为1的递增子序列
    int maxLength = 0;
    for (int i = 0; i < nums.size(); ++i) {
        for (int j = 0; j < i; ++j) {
            if (nums[i] > nums[j]) {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
        maxLength = max(maxLength, dp[i]); // 更新最长递增子序列的长度
    }
    return maxLength;
}

int main() {
    vector<int> nums = { 10, 9, 2, 5, 3, 7, 101, 18 };
    cout << "The length of the Longest Increasing Subsequence is: " << lengthOfLIS(nums) << endl;
    return 0;
}
  • 输出结果:

The length of the Longest Increasing Subsequence is: 4

  1. 代码仓库地址lengthOfLIS
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码流怪侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值