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

算法-动态规划

下面是使用 Java 实现动态规划(Dynamic Programming) 解决以下经典 DP 问题 的完整代码和说明:


✅ 1. 0-1 背包问题(Knapsack Problem)

问题描述:

给定 n 个物品,每个物品有重量 weights[i] 和价值 values[i],一个容量为 capacity 的背包。每个物品只能选一次,求能装入背包的最大总价值。

Java 实现:

public class Knapsack {public static int knapsack(int[] values, int[] weights, int capacity) {int n = values.length;int[][] dp = new int[n + 1][capacity + 1];for (int i = 1; i <= n; i++) {for (int w = 0; w <= capacity; w++) {if (weights[i - 1] <= w) {dp[i][w] = Math.max(dp[i - 1][w],dp[i - 1][w - weights[i - 1]] + values[i - 1]);} else {dp[i][w] = dp[i - 1][w];}}}return dp[n][capacity];}public static void main(String[] args) {int[] values = {60, 100, 120};int[] weights = {10, 20, 30};int capacity = 50;System.out.println(knapsack(values, weights, capacity)); // 输出 220}
}

✅ 2. 最长公共子序列(Longest Common Subsequence, LCS)

问题描述:

给定两个字符串 s1s2,找出它们的最长公共子序列(不连续,但顺序一致)。

Java 实现:

public class LCS {public static int longestCommonSubsequence(String s1, String s2) {int m = s1.length();int n = s2.length();int[][] dp = new int[m + 1][n + 1];for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (s1.charAt(i - 1) == s2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[m][n];}public static void main(String[] args) {String s1 = "abcde";String s2 = "ace";System.out.println(longestCommonSubsequence(s1, s2)); // 输出 3}
}

✅ 3. 最长递增子序列(Longest Increasing Subsequence, LIS)

问题描述:

给定一个整数数组,找出其中 最长递增子序列 的长度(子序列元素顺序不变,但可以不连续)。

Java 实现:

public class LIS {public static int lengthOfLIS(int[] nums) {int n = nums.length;int[] dp = new int[n];int maxLen = 0;for (int i = 0; i < n; i++) {dp[i] = 1;for (int j = 0; j < i; j++) {if (nums[i] > nums[j]) {dp[i] = Math.max(dp[i], dp[j] + 1);}}maxLen = Math.max(maxLen, dp[i]);}return maxLen;}public static void main(String[] args) {int[] nums = {10, 9, 2, 5, 3, 7, 101, 18};System.out.println(lengthOfLIS(nums)); // 输出 4(序列:2, 3, 7, 101)}
}

✅ 4. 编辑距离(Edit Distance)

问题描述:

给定两个字符串 word1word2,求将 word1 转换为 word2 所需的最少操作次数。操作包括:插入、删除、替换。

Java 实现:

public class EditDistance {public static int minDistance(String word1, String word2) {int m = word1.length();int n = word2.length();int[][] dp = new int[m + 1][n + 1];for (int i = 0; i <= m; i++) dp[i][0] = i;for (int j = 0; j <= n; j++) dp[0][j] = j;for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {if (word1.charAt(i - 1) == word2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1];} else {dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]),dp[i - 1][j - 1]);}}}return dp[m][n];}public static void main(String[] args) {String word1 = "horse";String word2 = "ros";System.out.println(minDistance(word1, word2)); // 输出 3}
}

✅ 5. 矩阵链乘法(Matrix Chain Multiplication)

问题描述:

给定一个矩阵链 p[0..n],其中第 i 个矩阵的维度为 p[i-1] x p[i],求矩阵相乘所需的最小乘法次数。

Java 实现:

public class MatrixChainMultiplication {public static int matrixChainOrder(int[] p) {int n = p.length - 1;int[][] dp = new int[n][n];for (int l = 2; l <= n; l++) { // 链长for (int i = 0; i < n - l + 1; i++) {int j = i + l - 1;dp[i][j] = Integer.MAX_VALUE;for (int k = i; k < j; k++) {int cost = dp[i][k] + dp[k + 1][j] + p[i] * p[k] * p[j];dp[i][j] = Math.min(dp[i][j], cost);}}}return dp[0][n - 1];}public static void main(String[] args) {int[] p = {1, 2, 3, 4}; // 矩阵维度:1x2, 2x3, 3x4System.out.println(matrixChainOrder(p)); // 输出 18}
}

✅ 总结对比表

问题时间复杂度空间复杂度核心思想
背包问题O(n * capacity)O(n * capacity)选或不选
LCSO(m * n)O(m * n)末尾字符匹配
LISO(n²)O(n)逐个比较前面元素
编辑距离O(m * n)O(m * n)插入/删除/替换
矩阵链乘法O(n³)O(n²)分割点枚举

这些算法是 动态规划中的经典问题,掌握它们有助于理解状态转移、子问题划分、边界处理等核心思想。在实际开发中,这些算法常用于 字符串处理、资源分配、优化计算顺序 等场景。

http://www.lryc.cn/news/592166.html

相关文章:

  • Paimon对比基于消息队列(如Kafka)的传统实时数仓方案的优势
  • 【动态规划 解析】
  • centos7安装MySQL8.4手册
  • 【PTA数据结构 | C语言版】二叉堆的快速建堆操作
  • Vue常见指令
  • Webpack 项目优化详解
  • mac mlx大模型框架的安装和使用
  • LangChain 源码剖析(三):连接提示词与大语言模型的核心纽带——LLMChain
  • FastAdmin后台登录地址变更原理与手动修改方法-后台入口机制原理解析-优雅草卓伊凡
  • 反序列化漏洞1-PHP序列化基础概念(0基础超详细)
  • 【C# in .NET】18. 探秘接口:契约精神
  • ARM64高速缓存,内存属性及MAIR配置
  • MariaDB 10.4.34 安装配置文档(Windows 版)
  • 性能远超Spring Cloud Gateway!Apache ShenYu如何重新定义API网关!
  • uniapp微信小程序 实现swiper与按钮实现上下联动
  • 网页的性能优化,以及具体的应用场景
  • 工业ESD防静电无尘净化棉签擦拭棒:精密制造领域的清洁守护者!
  • bash-completion未安装或未启用
  • 飞书,正在成为中国AI制造故事的新阵地
  • 【数据可视化-67】基于pyecharts的航空安全深度剖析:坠毁航班数据集可视化分析
  • 使用python的读取xml文件,简单的处理成元组数组
  • 如何防止GitHub上的敏感信息被泄漏?
  • Redis-集群与分区
  • Redis——BigKey
  • web开发基础(CSS)
  • 【甲烷数据集】Sentinel-5P 卫星获取的全球甲烷数据集-TROPOMI L2 CH₄
  • 设计循环队列oj题(力口622)
  • 四足机器人远程视频与互动控制的全链路方案
  • 声画同步!5 个音视频素材适配的网站,创作更和谐
  • 如何使用 Jackson 处理 YAML