Rosalind Java| Rabbits and Recurrence Relations

兔兔那么可爱为什么要生兔兔?
Rosalind编程问题之计算斐波那契数列,江湖也称不死神兔问题。

Rabbits and Recurrence Relations

Problem
A sequence is an ordered collection of objects (usually numbers), which are allowed to repeat. Sequences can be finite or infinite. Two examples are the finite sequence (π,−2–√,0,π) and the infinite sequence of odd numbers (1,3,5,7,9,…). We use the notation an to represent the n-th term of a sequence.

A recurrence relation is a way of defining the terms of a sequence with respect to the values of previous terms. In the case of Fibonacci’s rabbits from the introduction, any given month will contain the rabbits that were alive the previous month, plus any new offspring. A key observation is that the number of offspring in any month is equal to the number of rabbits that were alive two months prior. As a result, if Fn represents the number of rabbit pairs alive after the n-th month, then we obtain the Fibonacci sequence having terms Fn that are defined by the recurrence relation Fn=Fn−1+Fn−2 (with F1=F2=1 to initiate the sequence). Although the sequence bears Fibonacci’s name, it was known to Indian mathematicians over two millennia ago.

When finding the n-th term of a sequence defined by a recurrence relation, we can simply use the recurrence relation to generate terms for progressively larger values of n. This problem introduces us to the computational technique of dynamic programming, which successively builds up solutions by using the answers to smaller cases.

Given: Positive integers n≤40 and k≤5.

Return: The total number of rabbit pairs that will be present after n months, if we begin with 1 pair and in each generation, every pair of reproduction-age rabbits produces a litter of k rabbit pairs (instead of only 1 pair).

题目很好理解,斐波那契数列。只不过相较于我们最常见到的每代生育1个后代,题目换成了每代生育k个后代。其基本递归规律为Fn=Fn-1+kFn-2。我们在这里分别用两种方法,循环和递归来解决此问题。


方法1.循环法解决斐波那契

循环法把临位的三个数据理解为一个包含三个位的滑框:n-2位, n-1位, n位。每一次滑动这个滑框就要将新的值重新附在n-2, n-1, n三个位置。例如把上一轮n位置的数字赋值给下一轮n-1的位置,上一轮n-1位置的数字赋值给下一轮n-2的位置。java中利用重新赋值即可实现位置轮换。

import java.util.Scanner;

//兔子生兔子,每代生三个。新生的兔子在下一个月不produce,第二个月开始每个月生三个。
public class Rabbits_and_Recurrence_Relations {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入月份数n:");
        int n = sc.nextInt();

        Scanner sr = new Scanner(System.in);
        System.out.println("请输入每代兔子生育数k:");
        int k = sr.nextInt();

        System.out.println("第"+n+"个月后生育的兔子数为:"+rabbit(n, k));
    }

    //用循环方法解决斐波那契数列问题
    public static long rabbit(int n, int k) {
        long monthn_2 = 1;
        long monthn_1 = 1;
        long monthn = 0;
        //第n个月兔子数等于上一个月兔子数+上两个月兔子数*k
        for (int i = 0; i < n - 2; i++) {
            monthn = monthn_2 * k + monthn_1;
            monthn_2 = monthn_1;
            monthn_1 = monthn;
        }
        return monthn;
    }
}

方法2.递归法解决斐波那契

递归法利用的是方法内嵌套本方法实现迭代。实现的要点是设置一个终止点,在这里小编设置了初始月份1和2为1作为迭代终止。每实现一次循环运算,就会把n-1重新赋值回rabbitRecursion方法,直到n回到初始的1和2,返回前两个月的兔子数(斐波那契数量前两个月都是1)。

import java.util.Scanner;
//兔子生兔子,每代生三个。新生的兔子在下一个月不produce,第二个月开始每个月生三个。
public class Rabbits_and_Recurrence_Relations {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入月份数n:");
        int n = sc.nextInt();

        Scanner sr = new Scanner(System.in);
        System.out.println("请输入每代兔子生育数k:");
        int k = sr.nextInt();

        System.out.println("第"+n+"个月后生育的兔子数为:"+rabbitRecursion(n, k));

    }

    //用递归方法解决斐波那契数列问题
    public static long rabbitRecursion(int n, int k) {
        if (n ==2){
            return 1;
        } else if (n==1) {
            return 1;
        }else {
            return rabbitRecursion(n-1,k)+rabbitRecursion(n-2, k)*k;
        }
    }
}

补充.int 类型和long 类型变量

在实现本文的代码时,小编最初设置方法时,返回的变量类型为int即:

public static int rabbitRecursion(int n, int k)

public static int rabbit(int n, int k)

但是Rosalind给出的数据代入时却出现了bug甚至会有负数产生(可以试试public static int rabbit(33,4) )。但是借助python类似的代码却不会有这样的bug,究其原因是java语言中int类型变量数值范围有限。

int类型取值范围为-2147483648到±2147483648
long类型取值范围为-9223372036854775808到9223372036854775807

因此,当程序运行代数增多到int类型边界时就会出现bug,为了避免int类型范围造成的boundary问题,小编后来更换方法输出为long类型。但要注意long类型也有边界,对于极限代数或者生育数仍然会有超边界的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值