切蛋糕思维
大致可以分为三部
- 找重复
找到一种划分方法
找递推公式或者等价转换
都是父问题转化为求解子问题 - 找变化,变化的量通常作为参数
- 找边界:根据参数变化的趋势,对边界进行控制,适时终止递归
重复中的变化,变化中的重复!
1、数组累加
public class 递归_切蛋糕思维_数组累加 {
static int f3(int[] arr,int begin){
if(begin==arr.length-1 )
return arr[begin];
return arr[begin]+f3(arr,begin+1);
}
public static void main(String[] args){
int res=f3(new int[]{1,2,3,4,5},0);
System.out.println(res);
}
}
2、翻转字符串
public class 递归_切蛋糕思维_翻转字符串 {
public static void main(String[] args) {
System.out.println(reverse("sasdasdas",8));
}
static String reverse(String res,int end){
if (end==0)
return ""+res.charAt(0);
return res.charAt(end)+reverse(res,end-1);
}
}
注意:reverse中参数应该为字符串单个数量和-1
多分支遍历
3、斐波那契额数列
等价于两个子问题
1. 求第一项
2. 求第二项
3. 两项求和
public class 多分支遍历_斐波那契序列 {
public static void main(String[] args) {
System.out.println(fbnq(10));
}
static int fbnq(int n){
if (n==1||n==2)
return 1;
return fbnq(n-1)+fbnq(n-2);
}
}
4、最大公约数
public class 递推公式_最大公约数 {
public static void main(String[] args) {
System.out.println(f(27, 9));
}
static int f(int m, int n) {
if (n == 0)
return m;
return f(n, m % n);
}
}
4、插入排序
import java.util.Scanner;
public class 插入排序 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[] a = new int[n];
for (int i=0;i<n;i++){
a[i]=sc.nextInt();
}
f(a, n);
}
static void f(int[] a, int k) {
if (k == 0)
return;
f(a, k - 1);
int x = a[k];
int index = k - 1;
while (x < a[index]) {
a[index + 1] = a[index];
index--;
}
a[index] = x;
}
}
5、汉诺塔
1~N从A挪到B,C作为辅助
等价于:
1. 1~N-1从A挪到C,B作为辅助
2. 把N挪到B
3. 1~N-1从C挪到B,A作为辅助
public class 汉诺塔 {
public static void main(String[] args) {
printHaraiTower(3,"A","B","C");
}
static void printHaraiTower(int N,String from,String to,String help){
if (N==1)
System.out.println("move "+N+" from: "+from+" to: "+to);
else {
printHaraiTower(N-1,from,help,to);
System.out.println("move "+N+" from: "+from+" to: "+to);
printHaraiTower(N-1,help,to,from);
}
}
}
6、二分查找法
等价于三个子问题:
1. 左边找(递归)
2. 中间比
3. 右边找(递归)
左查找和右查找两者选其一
import java.util.Scanner;
public class 二分查找法 {
public static void main(String[] args) {
int[] n = new int[]{1, 2, 3, 4, 5};
Scanner sc = new Scanner(System.in);
int key = sc.nextInt();
if (key < n[n.length - 1] && key > n[0])
System.out.println(binarySearch(n, 1, 5, key));
else
System.out.println("关键值输入无效!");
}
public static int binarySearch(int[] arr, int low, int high, int key) {
if (low > high)
return -1;
int mid = low + ((high - low) >> 1);
int midVal = arr[mid];
if (midVal < key)
return binarySearch(arr, mid + 1, high, key);
else if (midVal > key)
return binarySearch(arr, low, high - 1, key);
else
return mid;
}
}