以下是Java实现的暴力递归版本,对应Go动态规划示例中的几个经典问题。暴力递归通常是最直观的解法,但效率较低,适合用来理解问题本质,之后可以优化为动态规划。
1. 斐波那契数列(暴力递归)
java
public class Fibonacci {
// 暴力递归实现(效率低,存在大量重复计算)
public static int fibRecursive(int n) {
if (n <= 1) {
return n;
}
return fibRecursive(n - 1) + fibRecursive(n - 2);
}
public static void main(String[] args) {
int n = 10;
System.out.println("斐波那契数列(暴力递归): " + fibRecursive(n));
}
}
2. 0-1背包问题(暴力递归)
java
public class Knapsack {
// 暴力递归实现
public static int knapsackRecursive(int[] weights, int[] values, int capacity, int index) {
if (index == weights.length || capacity == 0) {
return 0;
}
// 不选当前物品
int maxValue = knapsackRecursive(weights, values, capacity, index + 1);
// 选当前物品(如果容量允许)
if (weights[index] <= capacity) {
maxValue = Math.max(maxValue,
values[index] + knapsackRecursive(weights, values, capacity - weights[index], index + 1));
}
return maxValue;
}
public static void main(String[] args) {
int[] weights = {2, 3, 4, 5};
int[] values = {3, 4, 5, 6};
int capacity = 8;
System.out.println("背包最大价值(暴力递归): " +
knapsackRecursive(weights, values, capacity, 0));
}
}
3. 最长公共子序列(LCS,暴力递归)
java
public class LCS {
// 暴力递归实现
public static int lcsRecursive(String text1, String text2, int i, int j) {
if (i == text1.length() || j == text2.length()) {
return 0;
}
if (text1.charAt(i) == text2.charAt(j)) {
return 1 + lcsRecursive(text1, text2, i + 1, j + 1);
} else {
return Math.max(
lcsRecursive(text1, text2, i + 1, j),
lcsRecursive(text1, text2, i, j + 1)
);
}
}
public static void main(String[] args) {
String text1 = "abcde";
String text2 = "ace";
System.out.println("LCS长度(暴力递归): " + lcsRecursive(text1, text2, 0, 0));
}
}
4. 硬币找零问题(暴力递归)
java
import java.util.Arrays;
public class CoinChange {
// 暴力递归实现(返回最少硬币数)
public static int coinChangeRecursive(int[] coins, int amount, int index) {
if (amount == 0) {
return 0;
}
if (index == coins.length || amount < 0) {
return -1; // 无解
}
// 不选当前硬币
int res = coinChangeRecursive(coins, amount, index + 1);
// 选当前硬币
int next = coinChangeRecursive(coins, amount - coins[index], index);
if (next != -1) {
res = (res == -1) ? next + 1 : Math.min(res, next + 1);
}
return res;
}
public static void main(String[] args) {
int[] coins = {1, 2, 5};
int amount = 11;
System.out.println("最少硬币数(暴力递归): " +
coinChangeRecursive(coins, amount, 0));
}
}
暴力递归的缺点
- 重复计算 :如斐波那契数列中,
fib(n-2)会被计算多次。 - 效率低:时间复杂度通常是指数级(如背包问题为O(2^n))。
- 栈溢出风险:递归深度过大时可能导致栈溢出。
优化方向
这些暴力递归解法可以通过记忆化搜索 或动态规划优化,避免重复计算。例如:
- 斐波那契数列可以用缓存存储中间结果。
- 背包问题可以用二维数组保存子问题的解。
如果需要这些问题的Java动态规划实现,可以进一步补充!