当前位置: 首页 > news >正文

面试 TOP101 动态规划专题题解汇总Java版(BM62 —— BM82)

8月刷题挑战,多重好礼等你拿

动态规划

题号 题目名称 核心思路 时间复杂度 空间复杂度 代码亮点 牛客原题链接
BM62 斐波那契数列 动态规划(迭代) / 递归 O(n) / O(2ⁿ) O(1) / O(n) 迭代版空间 O(1) 优化 🔗 直达
BM63 跳台阶 DP:前两项和 O(n) O(1) 与斐波那契同模型 🔗 直达
BM64 最小花费爬楼梯 DP:min(前两项花费+成本) O(n) O(1) 边界 dp[0]=dp[1]=0 技巧 🔗 直达
BM65 最长公共子序列 二维 DP + 回溯构造子序列 O(n·m) O(n·m) 方向矩阵 b[][] 回溯输出 LCS 🔗 直达
BM66 最长公共子串 二维 DP + 记录 max 长度位置 O(n·m) O(n·m) 子串必须连续 🔗 直达
BM67 不同路径的数目(一) DP 累加 / 组合数 C(m+n-2,n-1) O(n·m) O(min(n,m)) 组合数写法更简洁 🔗 直达
BM68 矩阵的最小路径和 二维 DP:min(上,左)+当前值 O(n·m) O(n·m) 从左至右、从上至下 🔗 直达
BM69 数字翻译字符串 线性 DP:单双数字解码 O(n) O(1) 用于存储每个位置的解码方法数 🔗 直达
BM70 兑换零钱(一) 完全背包求最小硬币数 O(n·aim) O(aim) INF=0x3f3f3f3f 初始化技巧 🔗 直达
BM71 最长上升子序列 线性 DP + 贪心优化 O(n²) O(n) 初始化动态规划数组,每个位置的初始值为 1,因为每个元素自身可以看作长度为 1 的递增子序列 🔗 直达
BM72 连续子数组最大和 Kadane:max(前和+当前, 当前) O(n) O(1) 经典最大子段和 🔗 直达
BM73 最长回文子串 中心扩展 / Manacher O(n²) O(1) 奇偶中心双指针 🔗 直达
BM74 复原 IP 地址 三重循环枚举三段分割 O(1) O(1) 剪枝提前结束 🔗 直达
BM75 编辑距离(一) 二维 DP 经典 Levenshtein O(n·m) O(n·m) 可滚动数组优化 🔗 直达
BM76 正则表达式匹配 二维 DP:处理 *. O(n·m) O(n·m) 状态转移分三种情况 🔗 直达
BM77 最长括号子串 栈 / 线性 DP O(n) O(n) / O(1) 栈存索引或 DP 分段累加 🔗 直达
BM78 打家劫舍(一) 线性 DP:不相邻取数 O(n) O(1) dp[i]=max(dp[i-1],dp[i-2]+nums[i-1]) 🔗 直达
BM79 打家劫舍(二) 环形 DP:拆成两段线性 DP O(n) O(1) 两次 DP 取 max 🔗 直达
BM80 买卖股票(一) 一次交易 DP / 贪心 O(n) O(1) minPrice 贪心写法更简洁 🔗 直达
BM81 买卖股票(二) 无限交易贪心 / DP O(n) O(1) 贪心:累加所有上升段 🔗 直达
BM82 买卖股票(三) 最多两次交易状态机 DP O(n) O(1) 5 个状态滚动更新 🔗 直达

✅ 复习顺序建议(由易到难)

BM62 → BM63 → BM64 → BM69 → BM67 → BM68 → BM70 → BM71 → BM72 → BM77 → BM78 → BM79 → BM80 → BM81 → BM82 → BM65 → BM66 → BM75 → BM76

BM62 斐波那契数列

斐波那契数列_牛客题霸_牛客网
https://www.nowcoder.com/practice/c6c7742f5ba7442aada113136ddea0c3?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

  1. 动态规划
import java.util.*;public class Solution {// 1. 计算斐波那契数列的第 n 项public int Fibonacci(int n) {List<Integer> fib = new ArrayList<Integer>(); // 2. 创建一个列表,用于存储斐波那契数列fib.add(0); // 3. 添加第 0 项,值为 0fib.add(1); // 4. 添加第 1 项,值为 1for (int i = 2; i <= n; i++) { // 5. 从第 2 项开始计算,直到第 n 项fib.add(fib.get(i - 1) + fib.get(i - 2)); // 6. 计算当前项,值为前两项之和}return fib.get(n); // 7. 返回第 n 项的值}
}
  1. 空间优化 动态规划
import java.util.*;public class Solution {public int Fibonacci(int n) {if (n <= 1) return n;            // 1. 基准情况:F(0)=0, F(1)=1int a = 0, b = 1, c = 0;         // 2. 初始化 F(0), F(1), 临时变量for (int i = 2; i <= n; i++) {   // 3. 从 F(2) 递推到 F(n)c = a + b;                   // 4. 计算当前项a = b;                       // 5. 更新前两项b = c;}return c;                        // 6. 返回 F(n)}
}
  1. 递归
public class Solution {// 1. 计算斐波那契数列的第 n 项public int Fibonacci(int n) {// 2. 如果 n 小于等于 1,直接返回 n(第 0 项是 0,第 1 项是 1)if (n <= 1) return n;else {// 3. 根据斐波那契数列的定义,递归计算第 n 项return Fibonacci(n - 1) + Fibonacci(n - 2);}}
}

BM63 跳台阶

跳台阶_牛客题霸_牛客网
https://www.nowcoder.com/practice/8c82a5b80378478f9484d87d1c5f12a4?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {// 1. 计算青蛙跳到第 number 级台阶的方法数public int jumpFloor(int number) {List<Integer> dp = new ArrayList<>(); // 2. 创建一个列表,用于存储每级台阶的方法数dp.add(1); // 3. 第 0 级台阶有 1 种方法(即站在地上)dp.add(1); // 4. 第 1 级台阶有 1 种方法(跳1级)for (int i = 2; i <= 40; i++) { // 5. 从第 2 级台阶开始计算,直到第 40 级dp.add(dp.get(i - 1) + dp.get(i - 2)); // 6. 当前级的方法数等于前两级方法数之和}return dp.get(number); // 7. 返回第 number 级台阶的方法数}
}

BM64 最小花费爬楼梯

最小花费爬楼梯_牛客题霸_牛客网
https://www.nowcoder.com/practice/6fe0302a058a4e4a834ee44af88435c7?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj
2025年8月23日20:51:18 2025年8月23日20:57:18

import java.util.*;public class Solution {public int minCostClimbingStairs(int[] cost) {int n = cost.length; // 1. 获取楼梯的阶数int[] dp = new int[n + 1]; // 2. 创建一个数组,用于存储到达每一阶的最小成本// 3. 初始化前两阶的成本,因为可以从地面或第一阶开始,所以初始成本为0dp[0] = 0;dp[1] = 0;// 4. 从第2阶开始计算,直到第n阶for (int i = 2; i <= n; i++) {// 5. 到达第i阶的最小成本等于到达前两阶的最小成本加上对应的楼梯成本dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);}return dp[n]; // 6. 返回到达最后一阶的最小成本}
}

BM65 最长公共子序列(二)

最长公共子序列(二)_牛客题霸_牛客网
https://www.nowcoder.com/practice/6d29638c85bb4ffd80c020fe244baf11?tpId=295&tqId=991075&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {String x = ""; // 1. 存储第一个字符串String y = ""; // 2. 存储第二个字符串// 3. 递归函数,用于根据方向矩阵 b 构造 LCSString ans(int l1, int l2, int[][] b) {String res = ""; // 4. 初始化结果字符串if (l1 == 0 || l2 == 0) { // 5. 如果某个字符串的长度为 0,直接返回空字符串return res;}if (b[l1][l2] == 1) { // 6. 如果方向矩阵 b[l1][l2] 为 1,表示当前字符是 LCS 的一部分res += ans(l1 - 1, l2 - 1, b); // 7. 递归构造 LCS,并添加当前字符res += x.charAt(l1 - 1); // 8. 添加当前字符} else if (b[l1][l2] == 2) { // 9. 如果方向矩阵 b[l1][l2] 为 2,表示从上一个状态转移过来res += ans(l1 - 1, l2, b); // 10. 递归构造 LCS} else { // 11. 如果方向矩阵 b[l1][l2] 为 3,表示从左边的状态转移过来res += ans(l1, l2 - 1, b); // 12. 递归构造 LCS}return res; // 13. 返回构造的 LCS}// 14. 主函数,计算两个字符串的 LCSpublic String LCS(String s1, String s2) {int l1 = s1.length(); // 15. 获取第一个字符串的长度int l2 = s2.length(); // 16. 获取第二个字符串的长度if (l1 == 0 || l2 == 0) { // 17. 如果某个字符串为空,直接返回 "-1"return "-1";}x = s1; // 18. 存储第一个字符串y = s2; // 19. 存储第二个字符串int[][] dp = new int[l1 + 1][l2 + 1]; // 20. 创建动态规划表,用于存储 LCS 的长度int[][] b = new int[l1 + 1][l2 + 1]; // 21. 创建方向矩阵,用于记录构造 LCS 的路径// 22. 动态规划计算 LCS 的长度,并填充方向矩阵for (int i = 1; i <= l1; i++) {for (int j = 1; j <= l2; j++) {if (s1.charAt(i - 1) == s2.charAt(j - 1)) { // 23. 如果当前字符匹配dp[i][j] = dp[i - 1][j - 1] + 1; // 24. LCS 长度加 1b[i][j] = 1; // 25. 标记当前字符是 LCS 的一部分} else {if (dp[i - 1][j] > dp[i][j - 1]) { // 26. 如果从上一个状态转移过来的 LCS 更长dp[i][j] = dp[i - 1][j]; // 27. 更新 LCS 长度b[i][j] = 2; // 28. 标记从上一个状态转移过来} else { // 29. 如果从左边的状态转移过来的 LCS 更长dp[i][j] = dp[i][j - 1]; // 30. 更新 LCS 长度b[i][j] = 3; // 31. 标记从左边的状态转移过来}}}}String res = ans(l1, l2, b); // 32. 调用递归函数构造 LCSif (res.isEmpty()) { // 33. 如果结果为空,返回 "-1"return "-1";}return res; // 34. 返回构造的 LCS}
}

BM66 最长公共子串

最长公共子串_牛客题霸_牛客网
https://www.nowcoder.com/practice/f33f5adc55f444baa0e0ca87ad8a6aac?tpId=295&tags=&title=&difficulty=0&judgeStatus=0&rp=0&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {public String LCS(String str1, String str2) {int[][] dp = new int[str1.length() + 1][str2.length() + 1]; // 1. 创建动态规划表,用于存储最长公共子串的长度int max = 0; // 2. 初始化最长公共子串的长度int pos = 0; // 3. 初始化最长公共子串的结束位置// 4. 动态规划计算最长公共子串的长度for (int i = 1; i <= str1.length(); i++) {for (int j = 1; j <= str2.length(); j++) {if (str1.charAt(i - 
http://www.dtcms.com/a/361070.html

相关文章:

  • 【数学建模学习笔记】数据标准化
  • NUC029芯片解密和产品应用介绍
  • 玻璃门轻松更换智能密码锁,对接会议预约小程序的方法
  • 美术馆预约小程序|基于微信小程序的美术馆预约平台设计与实现(源码+数据库+文档)
  • Jenkins大总结 20250901
  • 今日分享:C++ -- vector
  • Linux 进程状态 — 僵尸进程
  • keil MDK如何使用第三方软件Keil2Json.exe生成compile_commands.json文件,方便vscode+clangd环境使用
  • Java面试-微服务(业务问题)
  • C#在物联网GPS经纬度转换为百度地图地址
  • 再见 K8s!3款开源的云原生部署工具
  • NetCoreKevin-DDD-微服务-WebApi-AI智能体、AISK集成、MCP协议服务、SignalR、Quartz 框架-15-认证与安全
  • DevExpress WinForms中文教程:Data Grid - 过滤编辑器
  • Spring事务管理策略对比与性能优化实践指南
  • k8s--etcd
  • CTFshow系列——命令执行web73-77(完结篇)
  • LeetCode Hot 100 Python (41~50)
  • .NET 微服务日志系统:Serilog + Loki + Grafana 实践指南
  • 安卓11 12系统修改定制化_____常用的几种修改固件 实现指定 “运行内存” 显示
  • 【论文精读】基于YOLOv3算法的高速公路火灾检测
  • ios 配置了代理且使用 chls.pro/ssl 下载不了证书,无法弹出下载证书的提示问题
  • 高防IP防护效果评估全攻略:从指标解读到实战测试
  • python填充多边形,获取所有内部点
  • JVM:内存区域划分、类加载的过程、垃圾回收机制
  • 电影票api接口对接步骤
  • Minecraft(我的世界)服务器信息查询免费API接口详解
  • Java PDF转多种图片格式:技术实践与性能优化
  • Flutter 本地持久化存储:Hive 与 SharedPreferences 实战对比
  • [吾爱出品] PDF文件加密解密工作,附带源码。
  • vercel上线资源无法加载