LeetCode-热题100:300. 最长递增子序列

本文介绍如何使用动态规划方法解决给定整数数组nums中的最长严格递增子序列问题。通过构造dp数组并进行状态转移,找到以数组元素结尾的最长上升子序列长度。示例代码清晰地展示了算法步骤和计算过程。
摘要由CSDN通过智能技术生成

题目描述

给你一个整数数组 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

代码及注释

func lengthOfLIS(nums []int) int {
    // 创建一个动态规划数组 dp,其中 dp[i] 表示以 nums[i] 结尾的最长上升子序列的长度
    dp := make([]int, len(nums))
    
    // 初始化结果为 1,因为每个单独的元素本身就是一个长度为 1 的上升子序列
    res := 1
    
    // 初始化 dp 数组的第一个元素为 1
    dp[0] = 1
    
    // 遍历整个数组
    for i := 1; i < len(nums); i++ {
        // 初始化 dp[i] 为 1,因为单个元素本身就是一个长度为 1 的上升子序列
        dp[i] = 1
        
        // 遍历当前元素之前的所有元素
        for j := 0; j < i; j++ {
            // 如果当前元素大于前面的某个元素,且加入当前元素后能构成更长的上升子序列
            if nums[i] > nums[j] {
                // 更新 dp[i],取当前的 dp[i] 和 dp[j] + 1(加入当前元素后的长度)的较大值
                dp[i] = max(dp[i], dp[j] + 1)
            }
        }
        
        // 更新结果 res,取当前的 res 和 dp[i] 的较大值
        res = max(res, dp[i])
    }
    
    // 返回结果 res,即最长的上升子序列的长度
    return res
}

// 辅助函数,返回两个整数中的较大值
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

代码解释

动态规划数组 dp

在这个问题中,我们使用动态规划来解决。我们定义了一个 dp 数组,其中 dp[i] 表示以 nums[i] 结尾的最长上升子序列的长度。通过这种方式,我们可以迭代地计算更长的上升子序列,并找到最长的一个。

1.初始化
  • 初始化 dp[0] 为 1,因为单个元素本身就是一个长度为 1 的上升子序列。
2.状态转移
  • 对于每个 nums[i],我们需要检查之前的所有元素 nums[j]j < i)。如果 nums[i] > nums[j],则说明我们可以将 nums[i] 加入到以 nums[j] 结尾的子序列中,从而构成一个更长的上升子序列。

  • 因此,我们更新 dp[i] = max(dp[i], dp[j] + 1)

3.更新结果
  • 每次更新 dp[i] 后,我们都更新全局的最长上升子序列长度 res
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值