Advertisement

最长递增子序列

阅读量:

最长自增子序列

原题链接

题目

给你一个整数数组 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 \\ -10^4 <= nums[i] <= 10^4

问题分析

根据题目可以得到三个条件

  • 最长
  • 递增
  • 子序列
    请添加图片描述

根据上图可以理解本题的意思

思路

利用动态规划的思想,自底向上 的进行求解。

设计状态

可以定义一个数组dp[i],表示以i结尾的最长递增子序列的长度为dp[i]

初始状态

对于每一个数来说,它自己可以单独成为一个递增的子序列,所以,数组初始化都为1

状态转移

那么对于dp[i]来说,dp[i]的值是怎么得到的呢?

首先,dp[i]肯定是在从自己开始(也就是dp[i] = 1) 和前一个递增的数的长度进行比较,选取最大值。

那么问题在于如何找到这所谓的前一个递增的数呢?

对于i而言,可以从第一个数遍历到 i - 1 个数,在从中与 dp[i] 进行比较,选择小的 dp[j] 进行 +1 ,这样便能够实现递增子序列长度的增加了。
img

根据以上动画能够理解上面所说的思路了

返回最终的解

在实现了 dp[i] 之后,就可以通过遍历数组求去最大值,该最大值便是最长递增子序列的长度

代码实现
复制代码
    class Solution {
    public int lengthOfLIS(int[] nums) {
        if (nums.length  == 0) return 0;
        int[] dp = new int[2510]; 
        Arrays.fill(dp, 1); // 初始化都为1
        int _max = 1; // 定义变量存取最长的长度
        for (int i = 1; i < nums.length; i++) {
            // 从第一个数开始逐个比较
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i]) { // 小于 即是递增的
                    // 执行状态转移
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                    // 记录最大值
                    _max = Math.max(_max, dp[i]);
                }
            }
        }
        // 返回最终的解
        return _max;
    }
    }

全部评论 (0)

还没有任何评论哟~