递归解释:就是使用自己的方法调用自己,直至达到出口的条件,才会终止对自己的调用
递归三要点
主要思路就是将大问题转化成小的子问题,在这个过程中,通常会有一些变化的量,这些量通常会作为参数进行变化。
1.找重复:找到一种划分方法
找到递推公式或者等价转换
以求n的阶乘为例:
要找n的阶乘就要找n-1的阶乘
2.找变化
由n变化到n-1
3.找边界
即找程序的出口,若没有出口则会一直调用自己,导致栈溢出
要找的边界就是在满足什么条件时结束该程序。
切蛋糕思维
案例:求阶乘
private static int f(int n) {
int result = 1;
if (n == 1) {
return result;
}
result = n * f(n-1);
return result;
}
输出x-->a之间的数
private static void f1(int x, int a){
if (a == x-1) {
return;
}
System.out.println(a);
f1(x,a-1);
}
求数组的和
private static int f2(int[] arr,int begin){
if (begin == arr.length) {
return 0;
}
return arr[begin] + f2(arr,begin+1);
}
反转字符串
private static String f3(String str,int end){
if (end == -1) {
return "";
}
return str.charAt(end) + f3(str,end-1);
}
一般的数学问题可以找递推公式,如:斐波那契数列和求最大公约数
二分查找的递归解法
等价于三个子问题
- 左边找(递归)
- 中间比
- 右边找(递归)
public class BinarySearch2 {
public static int rank(int key,int[] arr,int start,int end){
if(start >end){
return -1;
}
int mid=start+(end-start)/2;
if(key<arr[mid]){
return rank(key,arr,start,mid-1);
}else if(key>arr[mid]){
return rank(key,arr,mid+1,end);
}else{
return mid;
}
}
public static void main(String[] args) {
int arr[]={0,1,3,5,6,7,8,8,9}; System.out.println("resultPosition="+rank(3,arr,0,8));
}
}
递归解决全排列的问题
全排列的个数 n!;
通过迭代实现全排列:仅适用于长度为3或3以下的字符串
import java.util.ArrayList;
public class 全排列 {
public static void main(String[] args) {
String A = new String("ABC");
int n = A.length();
ArrayList<String> res = new ArrayList<>();
//初始化res,里面包含一个元素空字符串
res.add(A.charAt(0) +"");
for (int i = 1; i < n; i++) {
ArrayList<String> new_res = new ArrayList<>();
char c = A.charAt(i);
for (String str:
res) {
String newStr = c+str;
new_res.add(newStr);
newStr = str + c;
new_res.add(newStr);
for (int j = 1; j < str.length(); j++) {
newStr = str.substring(0,j) +c +str.substring(j);
new_res.add(newStr);
}
}
res = new_res;
}
}
}
通过递归来实现全排列
难点:如何实现多路递归
非字典序的全排列
在这个for循环里面先走完递归的循环,然后再进行下一个循环
即先纵后横

public class Main_2 {
public static void main(String[] args) {
perm(new int[]{1,2,3},0,2);
}
public static void perm(int[] array,int start,int end) {
if(start==end) {//递归的一个支路走到底了,输出一个。
System.out.println(Arrays.toString(array));
} else {
for (int i = start; i <= end; i++) {
//1,2,3的全排列这块相当于将其中一个提了出来,下次递归从start+1开始
swap(array,start,i);
perm(array,start+1,end);
//这块是复原数组,为了保证下次另外的同级递归使用数组不会出错
//这块可以通过树来理解,每次回退一步操作,交换回去
swap(array,start,i);//简称回溯
}
}
}
public static void swap(int[] array,int i,int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
没有维持字典序的原因
在交换的过程中[1,2,3]被换成了3[2,1]所以从第三次开始就不会再维持字典序,所以排出来的结果是321在前,312在后。
字典序全排列

网友评论