第17节.pptx
暴力递归就是尝试
1,把问题转化为规模缩小了的同类问题的子问题
2,有明确的不需要继续进行递归的条件(base case)
3,有当得到了子问题的结果之后的决策过程
4,不记录每一个子问题的解
题目1:汉诺塔问题
打印n层汉诺塔从最左边移动到最右边的全部过程
public static void hanoi(int n) {
fromLeftToRight(n);
System.out.println("===================");
process(n, "left", "right", "middle");
}
private static void fromLeftToRight(int n) {
if (n == 1) {
System.out.println("move 1 from left to right");
return;
}
fromLeftToMiddle(n - 1);
System.out.println("move " + n + " from left to right");
fromMiddleToRight(n - 1);
}
private static void fromMiddleToRight(int n) {
if (n == 1) {
System.out.println("move 1 from middle to right");
return;
}
fromMiddleToLeft(n - 1);
System.out.println("move " + n + " from middle to right");
fromLeftToRight(n - 1);
}
private static void fromMiddleToLeft(int n) {
if (n == 1) {
System.out.println("move 1 from middle to left");
return;
}
fromMiddleToRight(n - 1);
System.out.println("move " + n + " from middle to left");
fromRightToLeft(n - 1);
}
private static void fromLeftToMiddle(int n) {
if (n == 1) {
System.out.println("move 1 from left to middle");
return;
}
fromLeftToRight(n - 1);
System.out.println("move " + n + " from left to middle");
fromRightToMiddle(n - 1);
}
private static void fromRightToMiddle(int n) {
if (n == 1) {
System.out.println("move 1 from right to middle");
return;
}
fromRightToLeft(n - 1);
System.out.println("move " + n + " from right to middle");
fromLeftToMiddle(n - 1);
}
private static void fromRightToLeft(int n) {
if (n == 1) {
System.out.println("move 1 from right to left");
return;
}
fromRightToMiddle(n - 1);
System.out.println("move " + n + " from right to left");
fromMiddleToLeft(n - 1);
}
// 将以上递归进行抽象整合
private static void process(int n, String from, String to, String other) {
if (n == 1) {
System.out.println("move " + n + " from " + from + " to " + to);
return;
}
process(n - 1, from, other, to);
System.out.println("move " + n + " from " + from + " to " + to);
process(n - 1, other, to, from);
}
题目2:打印一个字符串的全部子序列
// 返回一个字符串的全部子序列
public static List<String> subSequence(String str) {
if (str == null || str.length() == 0) {
return null;
}
List<String> subString = new ArrayList<>();
char[] chars = str.toCharArray();
process(chars, 0, subString, "");
return subString;
}
private static void process(char[] chars, int index, List<String> ans, String curSubString) {
if (index == chars.length) {
ans.add(curSubString);
return;
}
// 没有要当前位置的字符
process(chars, index + 1, ans, curSubString);
// 要了当前位置的字符
process(chars, index + 1, ans, curSubString.concat(String.valueOf(chars[index])));
}
// 返回一个字面值字符串不重复的全部子序列
public static List<String> subSequenceNoRepeat(String str) {
if (str == null || str.length() == 0) {
return null;
}
HashSet<String> subString = new HashSet<>();
char[] chars = str.toCharArray();
process2(chars, 0, subString, "");
return new ArrayList<>(subString);
}
private static void process2(char[] chars, int index, HashSet<String> ans, String curSubString) {
if (index == chars.length) {
ans.add(curSubString);
return;
}
process2(chars, index + 1, ans, curSubString);
process2(chars, index + 1, ans, curSubString.concat(String.valueOf(chars[index])));
}
题目3:打印一个字符串的全部排列
// 返回一个字符串的全排列
public static List<String> allPermutation(String string) {
List<String> ans = new ArrayList<>();
if (string == null || string.length() == 0) {
return ans;
}
char[] str = string.toCharArray();
List<Character> chars = new ArrayList<>();
for (char c : str) {
chars.add(c);
}
process(chars, ans, "");
return ans;
}
private static void process(List<Character> chars, List<String> ans, String curSubString) {
if (chars.isEmpty()) {
ans.add(curSubString);
} else {
for (int i = 0; i < chars.size(); i++) {
char cur = chars.get(i);
chars.remove(i);
process(chars, ans, curSubString.concat(String.valueOf(cur)));
chars.add(i, cur);
}
}
}
public static List<String> allPermutation2(String string) {
List<String> ans = new ArrayList<>();
if (string == null || string.length() == 0) {
return ans;
}
char[] chars = string.toCharArray();
process2(chars, 0, ans);
return ans;
}
private static void process2(char[] chars, int index, List<String> ans) {
if (index == chars.length) {
ans.add(String.valueOf(chars));
} else {
for (int i = index; i < chars.length; i++) {
swap(chars, i, index);
process2(chars, index + 1, ans);
swap(chars, i, index);
}
}
}
private static void swap(char[] chars, int i, int j) {
char tmp = chars[i];
chars[i] = chars[j];
chars[j] = tmp;
}
// 去重的全排列
public static List<String> allPermutation3(String string) {
List<String> ans = new ArrayList<>();
if (string == null || string.length() == 0) {
return ans;
}
char[] chars = string.toCharArray();
process3(chars, 0, ans);
return ans;
}
private static void process3(char[] chars, int index, List<String> ans) {
if (index == chars.length) {
ans.add(String.valueOf(chars));
} else {
boolean[] visited = new boolean[256];
for (int i = index; i < chars.length; i++) {
// 剪枝 对于重复出现的字符,直接跳过
if (!visited[chars[i]]) {
visited[chars[i]] = true;
swap(chars, i, index);
process3(chars, index + 1, ans);
swap(chars, i, index);
}
}
}
}
题目4:逆序栈
给你一个栈,请你逆序这个栈,
不能申请额外的数据结构,
只能使用递归函数。 如何实现?
//给你一个栈,请你逆序这个栈,
//不能申请额外的数据结构,
//只能使用递归函数。 如何实现?
public static <T> void reverseStack(Stack<T> stack) {
if (stack == null || stack.empty()) {
return;
}
T last = precess(stack);
reverseStack(stack);
stack.push(last);
}
private static <T> T precess(Stack<T> stack) {
T cur = stack.pop();
if (stack.empty()) {
return cur;
} else {
T last = precess(stack);
stack.push(cur);
return last;
}
}