定义
1.把一个直接调用自己的或通过一系列的调用语句间接的调用自己的函数称为递归函数。
2.写递归最怕的就是陷入无限的循环中,所以递归函数必须至少有一个条件,满足递归不再进行,即不在引用自身而是返回值退出
3.我们在写递归函数时最好先写结束条件。
用处:将大型复杂问题化解为若干小问题进行求解
好处:代码量减少
弊端:占空间,函数是基于栈内存来运行的
要素:前进段,边界条件,返回段
递归的应用案列
阶乘
private static long f(long i) {
if(i==1||i==0){
return 1;
}
return i*f(i-1);
}
斐波那契数列的实现
1 1 2 3 5 8 13 21 34
前面相邻两项之和构成后一项
迭代方式:
public static void main(String[] args) {
int n=1;
int m=1;
int out=0;
for(int i=1;i<=50;i++){
if(i==1||i==2){
System.out.print(1+",");//1,2项特殊情况
}else{
out=n+m;
System.out.print(out+",");
n=m; //更新 m n
m=out;
}
}
递归方式:
public static int Fibo(int n){
if(n==1||n==2){
return 1;
}
return Fibo(n-1)+Fibo(n-2);
}
前进段与分治算法
分治算法思想:当问题求解过程相当复杂,我们可以将这类问题化成几个子问题,找到子问题的解法再把它们组合成整个问题的解法。子问题复杂的话还可以再化。
分治算法应用案例
遍历文件夹
public static void getFileALL(File file){
File [] files = file.listFiles();
if(files!=null){
for(File f : files){ //遍历文件夹中文件
if(f.isDirectory()){ //如果f还是文件夹再调用函数
getFileALL(f);
}else{
System.out.println(f);
}
}
}
}
二分查找
public int firstBadVersion(int n) {
int left = 1;
int right = n;
while(left<right){
int mid = left+(right-left)/2;
if(isBadVersion(mid)){
right = mid;
}else{
left = mid+1;
}
}
return right;
}
返回段与回溯算法
回溯算法实际是一个类似枚举的搜索尝试过程,主要在搜索尝试过程中当发现已不满足求解条件时,就回溯返回,尝试别的路径。
回溯算法是一种选优搜索法,当满足回溯条件的某个状态点称为回溯点。
八皇后问题
public static int count = 0;
private static void eigthQueue(int row, int[][] board) {
//如果行数小于八,说明还没解完
if(row>=8){
count++;
System.out.println("第"+count+"情况");
//打印二维数组
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
System.out.print(board[i][j]+" ");
}
System.out.println();
}
}else{
//复制棋盘
int[][] newBoard = new int[8][8];
for(int i=0;i<board.length;i++){
for(int j=0;j<board[i].length;j++){
newBoard[i][j] = board[i][j];
}
}
//更新棋盘
for(int col=0;col<8;col++){
if(noDangerous(row,col,newBoard)){
//放皇后前清空当前行
for(int c=0;c<8;c++){
newBoard[row][c] = 0; //当前行的值全置为0
}
newBoard[row][col] = 1; //放棋
eigthQueue(row+1, newBoard); //下一行,调用函数
}
}
}
}
//判断是否能够放棋
private static boolean noDangerous(int row, int col, int[][] newBoard) {
//正上方向
for(int r=row-1;r>=0;r--){
if(newBoard[r][col]==1){
return false;
}
}
//左上
for(int r=row-1,c=col-1;r>=0&&c>=0;r--,c--){
if(newBoard[r][c]==1){
return false;
}
}
//右上
for(int r=row-1,c=col+1;r>=0&&c<8;r--,c++){
if(newBoard[r][c]==1){
return false;
}
}
return true;
}