[Java 算法] 动态规划(4)

练习一 : 最长递增子序列

300. 最长递增子序列 - 力扣(LeetCode)

java 复制代码
class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        // 初始化:每个元素至少是长度为1的子序列
        Arrays.fill(dp, 1);
        int maxLen = 1;

        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                // 如果nums[i]可以接在nums[j]后面
                if (nums[i] > nums[j]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            maxLen = Math.max(maxLen, dp[i]);
        }
        return maxLen;
    }
}

算法原理

  1. DP 状态定义 : dp[i]:以 nums [i] 这个数字结尾的最长递增子序列长度。

  2. 初始化 : dp[i] = 1因为每个数字自己单独就是一个长度为 1 的递增子序列。

  3. 对于每个数 nums[i],看它前面所有的数 nums[j]只要 nums[j] < nums[i],说明 nums[i] 可以接在以 j 结尾的序列后面长度就变成:dp[j] + 1

练习二 : 摆动序列

376. 摆动序列 - 力扣(LeetCode)

java 复制代码
class Solution {
    public int wiggleMaxLength(int[] nums) {
        int n = nums.length;
        int[] f = new int[n];
        int[] g = new int[n];
        int ret = 1;
        for(int i = 0;i<n;i++) f[i] = g[i] = 1;
        for(int i = 1;i<n;i++){
            for(int j = i-1;j>=0;j--){
                if(nums[j]<nums[i]){
                    f[i] = Math.max(f[i],g[j]+1);
                }
                if(nums[j]>nums[i]){
                    g[i] = Math.max(g[i],f[j]+1);
                }
                ret = Math.max(Math.max(f[i],g[i]),ret);
            }
        }
        return ret;
    }
}

算法原理

  1. 状态定义(你用了两个 dp 数组,非常标准)
    f[i]:以 nums [i] 结尾,且最后一步是上升(nums [i] > 前一个数)的最长摆动序列长度
    g[i]:以 nums [i] 结尾,且最后一步是下降(nums [i] < 前一个数)的最长摆动序列长度
  2. 初始化 f[i] = g[i] = 1
    每个元素自己就是一个长度为 1 的摆动序列。
  3. 状态转移(你写得完全正确!)
    (1)当 nums [j] < nums [i] → 上升 说明i 可以接在 j 的下降序列后面 f[i] = max(f[i], g[j] + 1)
    (2)当 nums [j] > nums [i] → 下降 说明i 可以接在 j 的上升序列后面g[i] = max(g[i], f[j] + 1)
    摆动序列要求:上升 ↔ 下降 交替
    所以:
    想上升,必须接在下降结尾后面
    想下降,必须接在上升结尾后面
  4. 答案
    遍历过程中 f[i] 和 g[i] 的最大值

练习三 : 最长递增子序列的个数

673. 最长递增子序列的个数 - 力扣(LeetCode)

.

java 复制代码
class Solution {
    public int findNumberOfLIS(int[] nums) {
        int n = nums.length;
        int[] len = new int[n]; // 以i结尾的最长递增子序列长度
        int[] cnt = new int[n]; // 以i结尾的最长递增子序列的个数
        // 初始化
        for (int i = 0; i < n; i++) {
            len[i] = 1;
            cnt[i] = 1;
        }

        int maxLen = 1; // 全局最长长度
        // 填dp表
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i]) { // 严格递增
                    if (len[j] + 1 > len[i]) {
                        // 找到更长的序列,更新长度和计数
                        len[i] = len[j] + 1;
                        cnt[i] = cnt[j];
                    } else if (len[j] + 1 == len[i]) {
                        // 长度相同,累加计数
                        cnt[i] += cnt[j];
                    }
                }
            }
            // 更新全局最长长度
            maxLen = Math.max(maxLen, len[i]);
        }

        // 统计所有长度等于maxLen的个数之和
        int res = 0;
        for (int i = 0; i < n; i++) {
            if (len[i] == maxLen) {
                res += cnt[i];
            }
        }
        return res;
    }
}

算法原理

  1. 状态定义

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

cnt[i]:以 nums[i] 结尾的、长度为 len[i] 的最长递增子序列的个数

  1. 初始化

len[i] = 1:每个元素自身是长度为 1 的子序列

cnt[i] = 1:每个元素自身对应 1 个长度为 1 的子序列

  1. 状态转移

遍历每个 i,枚举所有 j < i:

若 nums[j] < nums[i](满足严格递增):

若 len[j] + 1 > len[i]:说明找到了更长的子序列,更新 len[i] = len[j] + 1,同时 cnt[i] = cnt[j](个数继承自 j)

若 len[j] + 1 == len[i]:说明找到了长度相同的新子序列,累加计数 cnt[i] += cnt[j]

若 nums[j] >= nums[i]:不满足严格递增,跳过

  1. 最终结果

先遍历 len 数组,找到全局最长长度 maxLen

再遍历所有 i,累加所有 len[i] == maxLen 的 cnt[i],即为答案

相关推荐
吃好睡好便好6 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
仰泳之鹅6 小时前
【C语言】自定义数据类型2——联合体与枚举
c语言·开发语言·算法
x_yeyue8 小时前
三角形数
笔记·算法·数论·组合数学
Mr. zhihao9 小时前
深入解析redis基本数据结构
数据结构·数据库·redis
念何架构之路10 小时前
Go语言加密算法
数据结构·算法·哈希算法
AI科技星10 小时前
《数学公理体系·第三部·数术几何》(2026 年版)
c语言·开发语言·线性代数·算法·矩阵·量子计算·agi
失去的青春---夕阳下的奔跑10 小时前
560. 和为 K 的子数组
数据结构·算法·leetcode
黎阳之光10 小时前
黎阳之光:以视频孪生重构智慧医院信息化,打造高标项目核心竞争力
大数据·人工智能·物联网·算法·数字孪生
丷丩11 小时前
三级缓存下MVT地图瓦片服务性能优化策略
算法·缓存·性能优化·gis·geoai-up
m0_6294947311 小时前
LeetCode 热题 100-----25.回文链表
数据结构·算法·leetcode·链表