- 暴力递归就是尝试
- 汉诺塔问题
- 打印一个字符串的全部子序列,包括空字符串
- 打印一个字符串的全部排列
- 打印一个字符串的全部排列,要求不要出现重复的排列
- 取牌游戏
- 给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数。
- 规定1和A对应、2和B对应、3和C对应、、、,那么一个数字字符串比如“111”,就可以转化为“AAA”、“KA”和“AK”。给定一个只有数字字符组成的字符串str,返回有多少种转化结果。
- 给定两个长度都为N的数组weights和values,weights[i]和values[i]分别代表i号物品的重量和价值。给定一个正数bag,表示一个载重bag的袋子,你装的物品不能超过这个重量。返回你能装下最多的价值是多少?
暴力递归就是尝试
- 把问题转化为规模缩小了的同类问题的子问题
- 有明确的不需要继续进行递归的条件(base case)
- 有当得到了子问题的结果之后的决策过程
- 不记录每一个子问题的解
- 一定要学会怎么去尝试,因为这是动态规划的基础
汉诺塔问题
打印n层汉诺塔从最左边移动到最右边的全部过程
public class Code01_Hanoi {public static void hanoi(int n) {if (n > 0) {func(n, n, "left", "mid", "right");}}public static void func(int rest, int down, String from, String help, String to) {if (rest == 1) {System.out.println("move " + down + " from " + from + " to " + to);} else {func(rest - 1, down - 1, from, to, help);func(1, down, from, help, to);func(rest - 1, down - 1, help, from, to);}}public static void main(String[] args) {int n = 3;hanoi(n);}}
打印一个字符串的全部子序列,包括空字符串

public class PrintAllSubsquences {public static void printAllSubsquence(String str) {char[] chs = str.toCharArray();process(chs, 0);}// 当前来到i位置,要和不要,走两条路// 之前的选择,所形成的结果,是strpublic static void process(char[] chs, int i) {if (i == chs.length) {System.out.println(String.valueOf(chs));return;}process(chs, i + 1);char tmp = chs[i];chs[i] = 0;process(chs, i + 1);chs[i] = tmp;}public static void function(String str) {char[] chs = str.toCharArray();process(chs, 0, new ArrayList<Character>());}// 当前来到i位置,要和不要,走两条路// res之前的选择,所形成的列表public static void process(char[] chs, int i, List<Character> res) {if(i == chs.length) {printList(res);}List<Character> resKeep = copyList(res);resKeep.add(chs[i]);process(chs, i+1, resKeep); // 要当前字符的路List<Character> resNoInclude = copyList(res);process(chs, i+1, resNoInclude); // 不要当前字符的路}public static void printList(List<Character> res) {// ...;}public static List<Character> copyList(List<Character> list){return null;}public static void main(String[] args) {String test = "abc";printAllSubsquence(test);}}
打印一个字符串的全部排列
打印一个字符串的全部排列,要求不要出现重复的排列
public class PrintAllPermutations {public static ArrayList<String> Permutation(String str) {ArrayList<String> res = new ArrayList<>();if (str == null || str.length() == 0) {return res;}char[] chs = str.toCharArray();process(chs, 0, res);res.sort(null);return res;}public static void process(char[] chs, int i, ArrayList<String> res) {if (i == chs.length) {res.add(String.valueOf(chs));}boolean[] visit = new boolean[26]; // 注释掉for (int j = i; j < chs.length; j++) {// 这叫分支限界,提前杀死不可能走的路if (!visit[chs[j] - 'a']) { // 注释掉 就是没有重复的排列visit[chs[j] - 'a'] = true; // 注释掉swap(chs, i, j);process(chs, i + 1, res);swap(chs, i, j);}}}public static void swap(char[] chs, int i, int j) {char tmp = chs[i];chs[i] = chs[j];chs[j] = tmp;}}
取牌游戏

public class CardsInLine {public static int win1(int[] arr) {if (arr == null || arr.length == 0) {return 0;}return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1));}public static int f(int[] arr, int i, int j) {if (i == j) {return arr[i];}return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));}public static int s(int[] arr, int i, int j) {if (i == j) {return 0;}return Math.min(f(arr, i + 1, j), f(arr, i, j - 1));}// 动态规划public static int win2(int[] arr) {if (arr == null || arr.length == 0) {return 0;}int[][] f = new int[arr.length][arr.length];int[][] s = new int[arr.length][arr.length];for (int j = 0; j < arr.length; j++) {f[j][j] = arr[j];for (int i = j - 1; i >= 0; i--) {f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]);s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]);}}return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]);}public static void main(String[] args) {int[] arr = { 1, 9, 1 };System.out.println(win1(arr));System.out.println(win2(arr));}}
给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数。
public class ReverseStackUsingRecursive {
public static void reverse(Stack<Integer> stack) {
if (stack.isEmpty()) {
return;
}
int i = getAndRemoveLastElement(stack);
reverse(stack);
stack.push(i);
}
public static int getAndRemoveLastElement(Stack<Integer> stack) {
int result = stack.pop();
if (stack.isEmpty()) {
return result;
} else {
int last = getAndRemoveLastElement(stack);
stack.push(result);
return last;
}
}
public static void main(String[] args) {
Stack<Integer> test = new Stack<Integer>();
test.push(1);
test.push(2);
test.push(3);
test.push(4);
test.push(5);
reverse(test);
while (!test.isEmpty()) {
System.out.println(test.pop());
}
}
}
规定1和A对应、2和B对应、3和C对应、、、,那么一个数字字符串比如“111”,就可以转化为“AAA”、“KA”和“AK”。给定一个只有数字字符组成的字符串str,返回有多少种转化结果。
public class ConvertToLetterString {
public static int number(String str) {
if (str == null || str.length() == 0) {
return 0;
}
return process(str.toCharArray(), 0);
}
// i... 有多少种转化的结果
public static int process(char[] chs, int i) {
if (i == chs.length) {
return 1;
}
if (chs[i] == '0') {
return 0;
}
if (chs[i] == '1') {
int res = process(chs, i + 1); // i自己作为单独的部分,后续有多少种方法
if (i + 1 < chs.length) {
res += process(chs, i + 2); //(i和i+1)作为单独的部分,后续有多少种方法
}
return res;
}
if (chs[i] == '2') {
int res = process(chs, i + 1); // i自己作为单独的部分,后续有多少种方法
//(i和i+1)作为单独的部分并且没有超过26,后续有多少种方法
if (i + 1 < chs.length && (chs[i + 1] >= '0' && chs[i + 1] <= '6')) {
res += process(chs, i + 2); //(i和i+1)作为单独的部分,后续有多少种方法
}
return res;
}
// str[i] == '3' ~ '9'
return process(chs, i + 1);
}
public static void main(String[] args) {
System.out.println(number("11111"));
}
}
给定两个长度都为N的数组weights和values,weights[i]和values[i]分别代表i号物品的重量和价值。给定一个正数bag,表示一个载重bag的袋子,你装的物品不能超过这个重量。返回你能装下最多的价值是多少?
public class Knapsack {
public static int maxValue1(int[] weights, int[] values, int bag) {
return process1(weights, values, 0, 0, bag);
}
// i... 的货物自由选择,形成的最大价值返回
// 重要永远不要超过bag
// 之前做的决定,所达到的重量,alreadyweight
public static int process1(int[] weights, int[] values, int i, int alreadyweight, int bag) {
if (alreadyweight > bag) {
return 0;
}
if (i == weights.length) {
return 0;
}
return Math.max(
// 不要当前i号货物的价值
process1(weights, values, i + 1, alreadyweight, bag),
// 要当前i号货物的价值
values[i] + process1(weights, values, i + 1, alreadyweight + weights[i], bag));
}
public static int maxValue2(int[] c, int[] p, int bag) {
int[][] dp = new int[c.length + 1][bag + 1];
for (int i = c.length - 1; i >= 0; i--) {
for (int j = bag; j >= 0; j--) {
dp[i][j] = dp[i + 1][j];
if (j + c[i] <= bag) {
dp[i][j] = Math.max(dp[i][j], p[i] + dp[i + 1][j + c[i]]);
}
}
}
return dp[0][0];
}
public static void main(String[] args) {
int[] weights = { 3, 2, 4, 7 };
int[] values = { 5, 6, 3, 19 };
int bag = 11;
System.out.println(maxValue1(weights, values, bag));
System.out.println(maxValue2(weights, values, bag));
}
}
