递归和动态规划问题
- 介绍:
- 暴力递归:
- 把问题转化为规模缩小了的同类问题的子问题
- 有明确的不需要继续进行递归的条件(base case)
- 有当得到了子问题的结果之后的决策过程
- 不记录每一个子问题的解
- 动态规划:
- 从暴力递归中来
- 将每一个子问题的解记录下来, 避免重复计算
- 把暴力递归的过程, 抽象成了状态表达
- 并且存在简化状态表达, 使其更加简洁的可能
- 暴力递归:
递归
- 阶乘
1
2
3
4
5
6public static long factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
} - 汉诺塔
1
2
3
4
5
6
7
8
9
10public static void hanoi(int N, String from, String help, String to) {
String format = String.format("Number: %d, From %s Use %s To %s", N, from, help, to);
if (N == 1) {
System.out.println(format);
} else {
hanoi(N - 1, from, to, help);
System.out.println(format);
hanoi(N - 1, help, from, to);
}
} - 打印一个字符串的所有子序列
1
2
3
4
5
6
7
8
9
10
11
12public static void printSubStr(String str) {
printSubStrProcess(str.toCharArray(), 0, "");
}
public static void printSubStrProcess(char[] str, int i, String res) {
if (i == str.length) {
System.out.println(res);
} else {
printSubStrProcess(str, i + 1, res);
printSubStrProcess(str, i + 1, res + str[i]);
}
} - 打印一个字符串的全排列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public static void printPermutation(String str) {
printPermutationProcess(str, "", str.length());
}
public static void printPermutationProcess(String str, StringBuffer res, int length) {
if (res.length() == length) {
System.out.println(res.toString());
} else {
for (int i = 0; i < str.length(); i++) {
res.append(str.charAt(i));
printPermutationProcess(str.substring(0, i) + str.substring(i + 1), res, length);
res.deleteCharAt(res.length() - 1);
}
}
} - 母牛每年生一只母牛, 新出生的母牛成长三年后也能每年生一只, 求N年后母牛的数量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public static int getCows(int N) {
if (N < 5) {
return N;
} else {
return getCows(N - 1) + getCows(N - 3);
}
// return getCowsProcess(N, 0, 0, 1, 1);
}
public static int getCowsProcess(int N, int c1, int c2, int c3, int current) {
if (current == N) {
return c1 + c2 + c3;
} else {
return getCowsProcess(N, c3, c1, c2 + c3, current + 1);
}
}
动态规划
- 给定一个二维数组, 二维数组中的每个数都是正数, 要求从左上角走到右下角, 每一步只能向右或者向下. 沿途经过的数字要累加起来. 返回最小的路径和.
1 | public static int getMinPathSum(int[][] arr) { |
- 给定一个数组arr, 和一个整数aim. 如果可以任意选择arr中的数字(每个数字只能使用一次), 能不能累加得到aim? 若能返回true, 否则返回false
1 | public static boolean isSum(int[] arr, int aim) { |