辛星Java动态规划教程第四篇:最长递增子序列(LIS),时间复杂度O(n^2)

本文详细介绍了求解最长递增子序列的两种方法:通过排序和最长公共子序列的结合,以及利用动态规划思想。动态规划方法中,通过维护一个数组记录每个元素前的最大递增子序列长度,实现O(n^2)的时间复杂度。

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

相对于最长公共子序列和最长公共子串来说,最长递增子序列的解法就要多一些了。

对于序列A来说,求它的递增子序列,比较简单的实现有很多种,我们本节介绍两种:

第一种解法就是对这个序列做一次排序,变成一个递增序列B,这样求A和B的公共子序列就等价于求A的递增子序列。

第二种解法就是使用动态规划的思路,这种思路也很多,可以维护一个长度为N的数组,这里的N的长度就是序列A的长度,它的每一项表示的是比序列A的元素小的可以组成的最大子序列的个数。这样当遇到比较大的数据的时候,可以直接复用数据较小的数据的结果。

第一种解法有些啰嗦,而且排序和最长公共子序列都介绍过了,相信读者朋友们可以自行实现。

第二种解法,其实就是对于每引入一个新的数据,就求一次比它小的数据的列表。
对于第二种解法,需要注意的是,第一个元素我们保存的是0还是1,如果我们保存的是0的话,那么最长递增子序列的长度要在所得的结果上加1,不要忘记这一点。
也有些人会在初始计算的时候就直接把所有数据都初始为1.

思路很简单,来看一下代码吧:

package com.mengzhidu.teach.algorithm.dp.demo.line;

/**
 * 最大递增子序列
 * 空间复杂度为O(n),时间复杂度为O(n^2)
 */
public class LisDemo1 {

    public static void main(String[] args) {
        int[] num = {1, 20, 30, 2, 3, 4, 80, 3, 90};
        lis(num);
    }

    private static void lis(int[] num) {
        if (num == null) {
            return;
        }

        int[] arr = new int[num.length];
        int max = 0;
        for (int i = 0; i < num.length; i ++) {
            for (int j = 0; j < i; j++) {
                if (num[i] > num[j] && arr[i] < arr[j] + 1) {
                    arr[i] = arr[j] + 1;
                    max = arr[i] > max ? arr[i] : max;
                }
            }
        }

        System.out.println("最长递增子序列的长度为:" + (max + 1));
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值