[Java 算法] 动态规划(4)
2026/4/6 10:21:42 网站建设 项目流程
练习一 : 最长递增子序列300. 最长递增子序列 - 力扣LeetCodeclass 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. 摆动序列 - 力扣LeetCodeclass 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;in;i) f[i] g[i] 1; for(int i 1;in;i){ for(int j i-1;j0;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; } }算法原理状态定义你用了两个 dp 数组非常标准f[i]以 nums [i] 结尾且最后一步是上升nums [i] 前一个数的最长摆动序列长度g[i]以 nums [i] 结尾且最后一步是下降nums [i] 前一个数的最长摆动序列长度初始化 f[i] g[i] 1每个元素自己就是一个长度为 1 的摆动序列。状态转移你写得完全正确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)摆动序列要求上升 ↔ 下降 交替所以想上升必须接在下降结尾后面想下降必须接在上升结尾后面答案遍历过程中 f[i] 和 g[i] 的最大值练习三 : 最长递增子序列的个数673. 最长递增子序列的个数 - 力扣LeetCode.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] 的最长递增子序列的个数2. 初始化len[i] 1每个元素自身是长度为 1 的子序列cnt[i] 1每个元素自身对应 1 个长度为 1 的子序列3. 状态转移遍历每个 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]不满足严格递增跳过4. 最终结果先遍历 len 数组找到全局最长长度 maxLen再遍历所有 i累加所有 len[i] maxLen 的 cnt[i]即为答案

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询