java-递归算法

一.基本定义
这里写图片描述
递归的效率差,但可以很方便的表达,做一些数学计算
1.求阶层
图示
这里写图片描述
求n!代码区

import java.util.Scanner;

public class Test {
    public static int Factorial(int n) {
        if (n < 0) {
            System.out.println("无效输入,请重新输入!");
            return 0;
        } else if (n == 1 || n == 0) {
            return 1;
        } else
            return n * Factorial(n - 1);
    }

    public static void main(String[] args) {
        System.out.println("input an integer: ");
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        System.out.println("the factorial of "+n+" is "+Factorial(n));
    }
}

四种方法

import java.math.BigInteger;//导入类
import java.util.ArrayList;
import java.util.List;

public class Test {//操作计算阶乘的类
    public static int simpleCircle(int num){//简单的循环计算的阶乘
        int sum=1;
        if(num<0){//判断传入数是否为负数
            throw new IllegalArgumentException("必须为正整数!");//抛出不合理参数异常
        }
        for(int i=1;i<=num;i++){//循环num
            sum *= i;//每循环一次进行乘法运算
        }
        return sum;//返回阶乘的值
    }
    public static int recursion(int num){//利用递归计算阶乘
        int sum=1;
        if(num < 0)
            throw new IllegalArgumentException("必须为正整数!");//抛出不合理参数异常
        if(num==1){
            return 1;//根据条件,跳出循环
        }else{
            sum=num * recursion(num-1);//运用递归计算
            return sum;
        }
    }
    public static long addArray(int num){//数组添加计算阶乘
        long[]arr=new long[21];//创建数组
        arr[0]=1;
        int last=0;
        if(num>=arr.length){
            throw new IllegalArgumentException("传入的值太大");//抛出传入的数太大异常
        }
        if(num < 0)
            throw new IllegalArgumentException("必须为正整数!");//抛出不合理参数异常
        while(last<num){//建立满足小于传入数的while循环
            arr[last+1]=arr[last]*(last+1);//进行运算
            last++;//last先进行运算,再将last的值加1
        }
        return  arr[num];
    }
    public static synchronized BigInteger bigNumber(int num){//利用BigInteger类计算阶乘

            ArrayList list = new ArrayList();//创建集合数组
            list.add(BigInteger.valueOf(1));//往数组里添加一个数值
            for (int i = list.size(); i <= num; i++) {
                BigInteger lastfact = (BigInteger) list.get(i - 1);//获得第一个元素
                BigInteger nextfact = lastfact.multiply(BigInteger.valueOf(i));//获得下一个数组
                list.add(nextfact);
            }
            return (BigInteger) list.get(num);//返回数组中的下标为num的值

    }

    public static void main(String []args){//java程序的主入口处
        int num=5;
        int num1=23;
        System.out.println("简单的循环计算"+num+"的阶乘为"//调用simpleCircle
                +simpleCircle(num));
        System.out.println("利用递归计算"+num+"的阶乘为"//调用recursion
                +recursion(num));
        System.out.println("数组添加计算"+num+"的阶乘为"//调用addArray
                +addArray(num));
        System.out.println("利用BigInteger类计算"+num1+"的阶乘为"//调用bigNumber
                +bigNumber(num1));

    }
}

2.求Fibonacci序列
1.定义:
0, 1, 1, 2, 3, 5, 8, 13, 21, …;
f0 = 0, f1 = 1, fn= fn−1 + fn−2 for n ≥ 2.

import java.util.Scanner;  
public class Fibonacci{   
    public static void main(String[] args) {  
            Scanner sc = new Scanner(System.in);  
            System.out.println("请输入一个大于零的整数:");  
            int n = sc.nextInt();  
            System.out.println("斐波那契数列为:");  
            for (int j = 1; j <= n; j++) {  
                System.out.print(fibonacci(j)+"  ");  
            }  
            //sc.close();  
        }   
        private static int fibonacci(int i) {    
            if (i == 1 || i == 2){  
                return 1;  
            }else{  
                return fibonacci(i - 1) + fibonacci(i - 2);  
            }    
        }  
    }  

3.汉诺塔问题
汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?
第一步:将n-1个盘子从A柱移动至B柱(借助C柱为过渡柱)
第二步:将A柱底下最大的盘子移动至C柱
第三步:将B柱的n-1个盘子移至C柱(借助A柱为过渡柱)
func:
if n!=0 then ;预定值
func(n-1, a, c, b) ;将n-1个盘子由a移动到b,以c为辅助柱子(注意参数顺序)
move a[n] to c ;将a上的最后一个盘子移动到c
func(n-1, b, a, c) ;将n-1个盘子由b移动到c,以a为辅助柱子
endif ;完成

public class Hanio {
    public static void main(String[] args){
        int i=3;
        char a ='A',b='B',c='C';
        hanio(i,a,b,c);
    }
    public static void hanio(int n,char a,char b,char c){
        if(n==1)
            System.out.println("移动"+n+"号盘子从"+a+"到"+c);
        else{
            hanio(n-1,a,c,b);//把上面n-1个盘子从a借助b搬到c
            System.out.println("移动"+n+"号盘子从"+a+"到"+c);//紧接着直接把n搬动c
            hanio(n-1,b,a,c);//再把b上的n-1个盘子借助a搬到c
        }
    }
}

方法二:
下面是使用Java实现的汉诺塔程序,程序使用Stack实例来保存每个柱子上的盘子及它们的顺序。Stack是队列的一种,其中的元素遵循“先进先出”(FIFO)的原则,即不允许从队尾取元素。这种队列通常也称为“栈”。栈对元素的进出约定与汉诺塔的规则一致。

resolve方法用来移动盘子,参数n表示要移动的盘子的数量,a是盘子所在的柱子,b是辅助柱子,c是目标柱子。注意此方法会首先检查参数n,当n为0时直接返回,这就是前面所说的“预定值”。如果没有对预定值的判断,resolve的递归过程将不会自然终止,而是无限进行下去,直到塞满系统内存堆栈而导致程序奔溃。

另外要注意的是程序将盘子的初始数量设为32个,你可以修改该值,但建议不要设置的过大,原因正如前面所计算的那样,如果采用64个圆盘,你将至少需要数百年才能看到结果(更可能的结果是由于步数太多,系统没有足够的内存而导致程序奔溃)。

import java.util.Iterator;
import java.util.Stack;
//Stack实例来保存每个柱子上的盘子及它们的顺序,Stack的先进先出的顺序
public class Hanio{
    //输出移动的盘子
      public static void print(Stack<Integer> s) {
            Iterator<Integer> i = s.iterator();
             while (i.hasNext()) {
                  System.out.printf("%d ", i.next());
            }
            System.out.println();
      }

      public static void resolve(int n, Stack<Integer> a, Stack<Integer> b, Stack<Integer> c) {
            if (n==0) return;
            resolve(n-1, a, c, b);//移动盘子,a移动到b,辅助B
            c.push(a.pop());
            resolve(n-1, b, a, c);//移动盘子,b移动到c,辅助a
      }

      public static void main(String[] args) {
            int count = 3;//总的砝码的重量
            Stack<Integer> a = new Stack<Integer>();
            Stack<Integer> b = new Stack<Integer>();
            Stack<Integer> c = new Stack<Integer>();

            for (int i=count; i>0; i--) {
                 a.push(i);
            }

            print(a);
            long start = System.currentTimeMillis();
            resolve(count, a, b, c);
            long end = System.currentTimeMillis();
            print(c);

            System.out.println((end - start)/1000);
      }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值