算法:递归

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法:递归相关的知识,希望对你有一定的参考价值。

* 递归:方法自己调用自己
* 步骤:找重复:将原问题转换成子问题,找变化量:作为参数,找边界:作为出口
* 学习方法:1-循环改递归,经典递归,大量练习,总结规律,最后挑战高难度递归

1. 键盘输入一个正整数,求该正整数的阶乘。

算法思路:找重复:f(n)=n*f(n-1);找参数n,找边界:n==0时候为f(n)=1。

import java.util.Scanner;

/**
 * 键盘输入一个正整数,求该正整数的阶乘
 */
public class FactorialDemo {
    public static int factorial(int n){
        if(n == 0){
            return 1 ;
        }
        return n * factorial(n - 1) ;
    }
    public static void main(String[] args){
        Scanner input = new Scanner(System.in) ;
        int number = input.nextInt() ;
        System.out.println(factorial(number)) ;
    }
}

求任意整数的阶乘,使用BigInteger对象,可以实现任意大的整数的阶乘。

import java.math.BigInteger;
import java.util.Scanner;

public class Factorial {
    public static BigInteger factorial(long n){
        BigInteger result = new BigInteger("1") ;
        for(int i=2; i<=n; i++){
            result = result.multiply(new BigInteger(i + "")) ;
        }
        return result ;
    }
    public static void main(String[] args){
        Scanner input = new Scanner(System.in) ;
        long n = input.nextLong() ;
        System.out.println(factorial(n)) ;
    }
}

2.  递归实现:键盘输入i和j,i<=j,打印从i到j的所有元素 。

算法思想:找重复:f(i,j)=i->f(i+1,j);找变化:i作为参数,找出口:i>j结束递归。

import java.util.Scanner;

public class PrintFromIToJ {
    public static void printFromIToJ(int i, int j){
        if(i > j){ //边界出口
            return ;
        }
        System.out.println(i) ; //i为变化的参数
        printFromIToJ(i+1,j) ; //重复的部分
    }
    public static void main(String[] args){
        Scanner input = new Scanner(System.in) ;
        int i = input.nextInt() ;
        int j = input.nextInt() ;
        printFromIToJ(i,j) ;
    }
}

3.递归实现求数组的所有元素之和。

算法思路:1-找重复:从第一个开始叠加; 2-找变换:变化的量作为参数,begin ; 3-找边界:当begin等于arr.length-1时,为递归出口。

public class ArraySum {
    public static int getArraySum(int [] arr, int begin){
        if(begin == arr.length-1){
            return arr[begin] ;
        }
        return arr[begin] + getArraySum(arr,begin+1) ;
    }
    public static void main(String[] args){
        int [] arr = {1,2,3,4,5,6,7,8,9,10} ;
        System.out.println(getArraySum(arr,0))  ;
    }
}

4.递归实现字符串的翻转。

算法思想:找重复:先打印最后一个字符,后面字符递归;找变化:字符串长度作为参数;找边界:当最后一个元素为字符串的第一个字符的时候为出口。

import java.util.Scanner;

public class Reverse {
    public static String reverse(String src, int end){
        if(end == 0){
            return src.charAt(0) + "" ;
        }
        return src.charAt(end) + reverse(src,end - 1) ;
    }
    public static void main(String[] args){
        Scanner input = new Scanner(System.in) ;
        String src = input.next() ;
        System.out.println(reverse(src,src.length()-1)) ;
    }
}

5.递归和迭代实现求斐波那契数列的第n项及前n项和。

 算法思想:找重复:f(n) = f(n-1) + f(n - 2) ,分解为多个小规模子问题 ;找变化:参数n ;找边界:当n==1或n==2时候为出口。

import java.util.Scanner;
public class Fibonacci {
    public static int fibonacci(int n){
        if(n == 1 || n == 2){
            return 1 ;
        }
        return fibonacci(n - 1) + fibonacci(n - 2) ;
    }
    public static void main(String[] args){
        Scanner input = new Scanner(System.in) ;
        int number = input.nextInt() ;
        System.out.println("斐波那契数列的第" + number +"项为:" + fibonacci(number) ) ;
        int sum = 0 ;
        for(int i=1; i<=number; i++){
            sum += fibonacci(i) ;
        }
        System.out.println("斐波那契数列的前" + number + "项和为:" + sum) ;
    }
}

6.递归实现求两个正整数的最大公约数和最小公倍数。

算法思想:找重复:f(m,n)=f(n,m%n);找变化:m,n;找边界:n等于0时候,为出口

m*n=最大公约数*最小公倍数


import java.util.Scanner;

public class GcdLcm {
    public static int gcd(int m, int n){
        if(n == 0){
            return m ;
        }
        return gcd(n,m % n) ;
    }
    public static void main(String[] args){
        Scanner input = new Scanner(System.in) ;
        int m = input.nextInt() ;
        int n = input.nextInt() ;
        System.out.println("最大公约数为:" + gcd(m,n)) ;
        System.out.println("最小公倍数为:" + (m * n) / gcd(m,n)) ;
    }
}

7. 插入排序的递归实现。

算法思想:找重复:对数组的k-1个元素进行排序,划分成子问题,将第k个元素插入;找变化:k作为参数;找边界:当k等于0时为出口。

public class InsertSortDemo {
    public static void insertSort(int [] arr, int k){
        if(k == 0){
            return ;
        }
        insertSort(arr,k-1) ;
        int x = arr[k] ;
        int index = k - 1 ;
        while(x < arr[index] && index >= 0){
            arr[index+1] = arr[index];
            index -- ;
            if(index < 0){
                break ;
            }
        }
        arr[index+1] = x ;
    }
    public static void main(String[] args){
        int [] arr = {2,1,5,4,3,9,7,8,0} ;
        insertSort(arr,arr.length-1) ;
        for(int i=0; i<arr.length; i++){
            System.out.print(arr[i] + " ") ;
        }
    }
}

8.汉诺塔游戏,将N个盘子从A移动到B,C为辅助,保证盘子N在最低部,1在最上部。

算法思想:将1-N-1个盘子从A移动到C,将第N个盘子从A移动到B,将1-N个盘子从C移动到B


public class HanoiTower {
    public static void hanoiTower(int N, String from, String to, String help) {
        if (N == 1) {
            System.out.println("将第" + N + "个盘子从" + from + "移动到" + to);
            return;
        }
        hanoiTower(N - 1, from, help, to);
        System.out.println("将第" + N + "个盘子从" + from + "移动到" + to);
        hanoiTower(N - 1, help, to, from);
    }
    public static void main(String[] args){
        hanoiTower(3, "A", "B", "C") ;
    }
}

9.二分查找的递归解法。

算法思想:找重复:关键字与中间元素进行比较,每次缩小查询范围。找变化:low和high在不断的变化,故作为参数。找边界:当low>high时候为出口。

public class BinarySearch {
    public static int binarySearch(int [] arr, int low, int high, int key){
        int mid = (low + high) >>> 1 ;
        if(low > high){ //出口
            return -1 ;
        }
        if(key > arr[mid]){
            return binarySearch(arr,mid+1, high, key) ;
        }
        else if(key < arr[mid]){
            return binarySearch(arr, low, mid-1, key) ;
        }
        else{
            return mid ;
        }
    }
    public static void main(String[] args){
        int [] arr = {1,2,3,4,6,7,8,9} ;
        System.out.println(binarySearch(arr,0,arr.length-1, 7)) ;
    }
}

10.小白上楼梯。小白正在上楼梯,楼梯有n阶台阶,键盘输入n,小白一次可以上1阶,2阶或者3阶,  实现一个方法,计算小白有多少种走完楼梯的方式,打印输入方式种数?


import java.util.Scanner;

public class ClimbStair {
    public static int f(int n){
        if(n == 1){
            return 1 ;
        }
        if(n == 2){
            return 2 ;
        }
        if(n == 3){
            return 4 ;
        }
        return f(n-1) + f(n-2) + f(n-3) ;
    }
    public static void main(String[] args){
        Scanner input = new Scanner(System.in) ;
        int n = input.nextInt() ;
        System.out.println(f(n)) ;
    }
}

11.在有空字符串的有序字符串数组中查找 ,有个排序后的字符串数组,其中散布着一些空字符串, 编写一个方法,找出给定字符串(肯定不是空字符串)的索引。

算法思想:对于有序字符串数组的查找,可以采用二分查找的思想,将目标值与中间值比较,不断折半,缩小查找范围,直至查找结束。

public class Search {
    public static int search(String [] arr, String target){
        int low = 0 , high = arr.length-1 ;
        while(low <= high){
            int mid = (low + high) >>> 1 ;
            while(arr[mid].equals("")){
                mid ++ ;
                if(mid > high){
                    return -1 ;
                }
            }
            if(arr[mid].compareTo(target) > 0){
                high = mid - 1 ;
            }
            else if(arr[mid].compareTo(target) < 0){
                low = mid + 1 ;
            }
            else{
                return mid ;
            }
        }
        return -1 ;
    }
    public static void main(String[] args){
        String [] arr = {"a", "", "ac", "", "ad", "", "b", "", "ba"} ;
        System.out.println(search(arr,"ba")) ;
    }
}

12.最长连续递增子序列(部分有序) ,(1925734680)中最长的递增子序列为(3468)

算法思想:采用双指针,记录移动的位置以及最大连续递增序列的长度。

public class SubDemo {
    public static String sub(String s){
       int low = 0, high = 1, length = 0, maxLength = 0, end = 0 ;
       while(low != s.length()-1){
           if(s.charAt(high) > s.charAt(low)){
               low ++ ;
               high ++ ;
               length ++ ;
               if(length > maxLength){
                   maxLength = length ;
                   end = low ;
               }
           }
           else{
               low ++ ;
               high ++ ;
               length = 0 ;
           }
       }
       String result = "" ;
       for(int i=end-maxLength; i<=end; i++){
           result += s.charAt(i) ;
       }
       return result ;

    }
    public static void main(String[] args){
        String s = "1925734680" ;
        System.out.println(sub(s)) ;
    }
}

13.递归求解整数a的n次整数幂。

算法思路:先算偶数次方,再递归算奇数次方。

import java.util.Scanner;

public class GetPowerDemo {
    public static int pow(int a, int n){
        int ex = 1, res = a;
        if(n == 0){
            return 1 ;
        }
        while((ex<<1) <= n){
            res *= pow(a,ex) ;
            ex <<= 1 ;
        }
        return res * pow(a,n-ex);
    }
    public static void main(String[] args){
      Scanner input = new Scanner(System.in) ;
      int a = input.nextInt() ;
      int n = input.nextInt() ;
      System.out.println(pow(a,n)) ;
    }
}

以上是关于算法:递归的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript - 代码片段,Snippets,Gist

以下代码片段的算法复杂度

有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]

片段(Java) | 机试题+算法思路+考点+代码解析 2023

CSP核心代码片段记录

算法漫游指北(第十篇):泛型递归递归代码模板递归思维要点分治算法回溯算法