最长上升子序列

题目链接https://www.acwing.com/problem/content/897/
image.png

一、求最长上升子序列长度

这个题其实还是跟之前一样的思路,f[i]可以看作以num[i]为末尾的最长子序列的长度集合,现在要求集合中的最大值。f[i]可以用f[j]+1来表示,此处j是这个上升子序列的倒数第二个值,用循环来求

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] num = new int[1005];
        int[] f = new int[1005];
        for(int i = 1; i <= n; i++) num[i] = in.nextInt();

        for(int i = 1; i <= n; i++) {
            f[i] = 1;
            for(int j = 1; j <= n; j++) {
                if(num[i] > num[j]) {
                    f[i] = Math.max(f[i],f[j] + 1);
                }
            }
        }
        int res = 0;
        for(int i = 1; i<= n;i++) {
            res = Math.max(f[i],res);
        }
        System.out.print(res);
    }
}

二、打印最长上升子序列(倒序输出)

打印最长子序列的时候可以用g[i]数组来表示每个以num[i]结尾的最长上升子序列的上一个数在num数组中的下标。
以输入样例为例

下标01234567
num3121856
f1121334
g0020336
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int[] num = new int[1005];
        int[] f = new int[1005];
        int[] g = new int[1005];
        for(int i = 1; i <= n; i++) num[i] = in.nextInt();

        for(int i = 1; i <= n; i++) {
            f[i] = 1;
            g[i] = 0;
            for(int j = 1; j < i; j++) {
                if(num[i] > num[j]) {
                    if(f[i] < f[j] + 1){
                        f[i] = f[j] + 1;
                        // g[i]存的是以i结尾的序列的倒数第二个数在num中的下标
                        g[i] = j;
                    }
                }
            }
        }
        // 这个循环取出最大值
        int k = 1;
        for(int i = 1; i<= n;i++) {
            if (f[k] < f[i]) k = i;
        }
        System.out.println(f[k]);
        // 这个循环取出路径,输出为倒序
        for (int i = 0, len = f[k]; i < len; i++) {
            System.out.print(num[k]+" ");
            k = g[k];
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值