递归
暴力递归:
- 把问题转化为规模缩小了的同类问题的子问题
- 有明确的不需要继续进行递归的条件(base case)
- 有当得了子问题得结果之后得决策过程4,不记录每一个子问题得解
1.求n!
/*
* 求n!
* */
public static long getFactorial1(int n){
if (n == 1){
return 1L;
}
return (long) n * getFactorial1(n - 1);
}
/*
* 非递归求n!
* */
public static long getFactorial2(int n){
long result = 1L;
for (int i = 1; i <= n; i++){
result *= i;
}
return result;
}
2.汉诺塔
/*
* 汉诺塔
* from to help
* 1) 1-(n-1) from -> help
* 2) n from -> to
* 3) 1-(n-1) help -> to
* */
public static void Hanoi(int N, String from, String to, String help){
if(N == 1){
System.out.println("Move 1 from " + from + " to " + to);
} else {
Hanoi(N - 1, from, help, to);
System.out.println("Move " + N + " from " + from + " to " + to);
Hanoi(N - 1, help, to, from);
}
}
/*
* 1) 1-(n-1) left -> mid
* 2) n left -> right
* 3) 1-(n-1) mid -> right
* */
public static void moveLeftToRight(int N){
if(N == 1){
System.out.println("move 1 from left to right");
} else {
moveLeftToMid(N - 1);
System.out.println("move " + N + " from left to right");
moveMidToRight(N - 1);
}
}
/*
* 1) 1-(n-1) left -> right
* 2) n left -> mid
* 3) 1-(n-1) right -> mid
* */
public static void moveLeftToMid(int N){
if(N == 1){
System.out.println("move 1 from left to mid");
} else {
moveLeftToRight(N - 1);
System.out.println("move " + N + " from left to mid");
moveRightToMid(N - 1);
}
}
/*
* 1) 1-(n-1) right -> left
* 2) n right -> mid
* 3) 1-(n-1) left -> mid
* */
public static void moveRightToMid(int N){
if(N == 1){
System.out.println("move 1 from right to mid");
} else {
moveRightToLeft(N - 1);
System.out.println("move " + N + " from right to mid");
moveLeftToMid(N - 1);
}
}
/*
* 1) 1-(n-1) mid -> left
* 2) n mid -> right
* 3) 1-(n-1) left -> right
* */
public static void moveMidToRight(int N){
if(N == 1){
System.out.println("move 1 from mid to right");
} else {
moveMidToLeft(N - 1);
System.out.println("move " + N + " from mid to right");
moveLeftToRight(N - 1);
}
}
/*
* 1) 1-(n-1) mid -> right
* 2) n mid -> left
* 3) 1-(n-1) left -> right
* */
public static void moveMidToLeft(int N){
if(N == 1){
System.out.println("move 1 from mid to left");
} else {
moveMidToRight(N - 1);
System.out.println("move " + N + " from mid to left");
moveLeftToRight(N - 1);
}
}
/*
* 1) 1-(n-1) right -> mid
* 2) n right -> left
* 3) 1-(n-1) left -> mid
* */
public static void moveRightToLeft(int N){
if(N == 1){
System.out.println("move 1 from right to left");
} else {
moveRightToMid(N - 1);
System.out.println("move " + N + " from right to left");
moveLeftToMid(N - 1);
}
}
Hanoi输出
move 1 from left to right
move 2 from left to mid
move 1 from right to mid
move 3 from left to right
move 1 from mid to left
move 2 from mid to right
move 1 from left to right
3. 子序列
/*
* 打印一个字符串得全部子序列,包括空字符串
* str = "abc"
* subsequence = ["abc", "ab", "ac", "a", "bc", "b", "c", ""]
* */
public static void printAllSubsequence(char[] str, int i, String res){
if(i == str.length){
System.out.println(res);
return;
}
//不要当前字符
printAllSubsequence(str, i + 1, res);
//要当前字符
printAllSubsequence(str, i + 1, String.valueOf(str[i]));
}
输出
c
b
bc
a
ac
ab
abc
4. 打印字符串全排列
打印一个字符串得全排列
public static void printAllPermutations1(String str){
char[] chs = str.toCharArray();
process1(chs, 0);
}
public static void process1(char[] chs, int i){
//base case
if(i == chs.length){
System.out.println(String.valueOf(chs));
}
for (int j = i; j < chs.length; j++){
//i位置和j位置的字符交换
swap(chs, j, i);
//跑剩下位置的字符
process1(chs, i + 1);
}
}
public static void swap(char[] chs, int j, int i){
char tmp = chs[j];
chs[j] = chs[i];
chs[i] = tmp;
}
打印一个字符串的全部排列,要求不要出现重复的排列
public static void printAllPermutations2(String str){
char[] chs = str.toCharArray();
process2(chs, 0);
}
public static void process2(char[] chs, int i){
if(i == chs.length){
System.out.println(String.valueOf(chs));
}
HashSet<Character> set = new HashSet<>();
for (int j = i; j < chs.length; j++){
if(!set.contains(chs[j])){
set.add(chs[j]);
swap(chs, i, j);
process2(chs, i + 1);
}
}
}
输出结果
abc
acb
cab
cba
abc
acb
======
abc
acb
cab
cba
======
acc
acc
cac
cca
acc
acc
======
acc
cac
cca
======
5. 母牛生牛
母牛每年生一只母牛,新出生的母牛成长三年后也能每年生一只母牛,假设不会死。求N年后,母牛的数量。
public static int cow(int year){
if(year < 1){
return 0;
}
if(year == 1 || year == 2 || year == 3){
return year;
}
return cow(year - 1) + cow(year - 3);
}
如果每只母牛只能活10年,求N年后,母牛的数量。
F(N) = F(N - 1)+F(N - 3)-F(N - 10)
public static int cow2(int year){
if(year < 1){
return 0;
}
if(year == 1 || year == 2 || year == 3){
return year;
}
if(year < 10)
return cow(year - 1) + cow(year - 3);
return cow(year - 1) + cow(year - 3) - cow(year - 10);
}
6. 逆序栈
给你一个栈,请你逆序这个栈,不能申请额外的数据结构,只能使用递归函数。如何实现
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;
}
}