最长递增子序列的个数(200分 / 动态规划)

题目描述 :给定一个整数数组 nums(长度 n ≤ 2000,元素范围 -10^6 ~ 10^6),求最长严格递增子序列 的个数。若最长递增子序列长度为 L,输出长度为 L 的不同子序列个数(下标不同即视为不同)。

输入:

  • 第一行:n

  • 第二行:n 个整数

输出:最长递增子序列的个数。

示例:

text

复制代码
输入:
5
1 3 5 4 7

输出:
2

解释:最长递增子序列长度为 4,有两个:1 3 5 7 和 1 3 4 7。

解题思路

维护两个数组:

  • dp[i]:以 nums[i] 结尾的最长递增子序列长度。

  • cnt[i]:以 nums[i] 结尾的最长递增子序列个数。

转移:

  • 若 nums[j] < nums[i]:

    • 若 dp[j] + 1 > dp[i]:dp[i] = dp[j] + 1,cnt[i] = cnt[j]

    • 若 dp[j] + 1 == dp[i]:cnt[i] += cnt[j]

最后统计所有 dp[i] == L 的 cnt[i] 之和。

参考代码

c

复制代码
#include <stdio.h>

int main(void) {
    int n;
    scanf("%d", &n);

    int nums[2005];
    for (int i = 0; i < n; i++) scanf("%d", &nums[i]);

    int dp[2005];
    long long cnt[2005]; // 个数可能较大,用 long long

    for (int i = 0; i < n; i++) {
        dp[i] = 1;
        cnt[i] = 1;
    }

    int maxLen = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (nums[j] < nums[i]) {
                if (dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1;
                    cnt[i] = cnt[j];
                } else if (dp[j] + 1 == dp[i]) {
                    cnt[i] += cnt[j];
                }
            }
        }
        if (dp[i] > maxLen) maxLen = dp[i];
    }

    long long ans = 0;
    for (int i = 0; i < n; i++) {
        if (dp[i] == maxLen) ans += cnt[i];
    }

    printf("%lld\n", ans);
    return 0;
}
相关推荐
一去不复返的通信er16 小时前
力扣-图论-岛屿数量
算法·leetcode·图论
程序 代码狂人19 小时前
切片表与分区表的区别(数据开发面试版)
java·大数据·开发语言·数据仓库·算法
HDU-Dade19 小时前
【校招笔试真题】简要介绍 Self-Attention 的前沿算法
人工智能·算法
小郎君65821 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
算法
邵奈一1 天前
GPT-6.1 Terra速度是Sol的3倍,价格减半
算法
RaaS1001 天前
Node.js Brotli RCE 漏洞自查指南:fetch、undici、axios 都在影响面,三分钟确认你的版本
人工智能·深度学习·算法
shehuiyuelaiyuehao1 天前
算法56,重排链表
数据结构·算法·链表
qq_452396231 天前
第四篇:《索引原理与实战:B-tree、Hash、GIN、GiST、BRIN》
算法·哈希算法·gin
西索斯coding1 天前
Qwen3-Max 与 Qwen-Plus:60 个真实修复任务评测方案
大数据·网络·算法·ai