萌新卷妹带你从头复习JavaSE-方法2

举报
京与旧铺 发表于 2022/10/31 17:49:17 2022/10/31
【摘要】 萌新卷妹带你从头复习JavaSE-方法2🍦3.1斐波拉契数列斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963起出版了...

萌新卷妹带你从头复习JavaSE-方法2

🍦3.1斐波拉契数列

斐波那契数列,又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。 特别指出:第0项是0,第1项是第一个1。这个数列从第3项开始,每一项都等于前两项之和。

🍁斐波拉契数列的通项公式为:F(N) = F(N - 1) + F(N -2) 🍁起始条件:N = 0,F(0) = 0; N = 1,F(1) = 1; 🍁递归实现:

public class testBlog {
    public static int fib1(int  n) {
        if (n == 0 || n == 1) {
            return n;
        }
        return fib1(n - 1) + fib1(n - 2);
    }
    public static void main(String[] args) {
        //斐波拉契数列
        for (int i = 0; i < 13; i++) {
            System.out.print(fib1(i) + "  ");
        }
    }
}

6 但是使用递归实现斐波拉契数列,求后面的项会变得越来越慢,因为会进行大量重复的项的计算。 🍁推荐使用迭代的方法实现:

public class testBlog {
    //fib1递归,fib2迭代
    public static int fib1(int  n) {
        if (n == 0 || n == 1) {
            return n;
        }
        return fib1(n - 1) + fib1(n - 2);
    }
    public static int fib2(int n) {
        if (n == 0 || n == 1) {
            return n;
        }
        int f0 = 0;
        int f1 = 1;
        int fn = 0;
        while (n - 1 != 0) {
            fn = f0 + f1;
            f0 = f1;
            f1 = fn;
            n--;
        }
        return fn;
    }
    public static void main(String[] args) {
        //斐波拉契数列
        for (int i = 0; i < 13; i++) {
            System.out.print(fib1(i) + "  ");//递归结果
        }
        System.out.println();
        for (int i = 0; i < 13; i++) {
            System.out.print(fib2(i) + "  ");//迭代结果
        }
    }
}

7

🍦3.2青蛙跳台阶问题

🍧3.2.1题目描述及思路

🍁题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级的台阶总共有多少种跳法? 解题思路 1.当n=1的时,很明显青蛙只有一种跳法。 2.当n=2时,青蛙有两种选择,一是每次跳1级台阶,跳两次,二是直接跳两级台阶,一步到位。所以,一共有两种跳法。 3.当n>2时,我们不妨把上n级台阶的跳法记为一个函数f(n),青蛙在第一次跳的时候有两个选择,即跳一级台阶或跳两级台阶。当青蛙选择第一次跳一级台阶时,跳完后还剩n-1级台阶,在此情况下,跳法的数目为f(n-1);当青蛙选择第一次跳两级台阶时,跳完后还剩n-2级台阶,在此情况下,跳法数目为f(n-2)。所以,我们可以推出青蛙跳n级台阶的跳法总数为f(n)=f(n-1)+f(n-2)。

到这里我们就能使用求斐波拉契数列的方法来求青蛙跳n级台阶的跳法。

🍁若把条件修改成一次可以跳一级,也可以跳2级...也可以跳上n级呢? 解题思路 尽管条件改成每次跳的台阶级数不受限,但是换汤不换药,思考的方法是一样的。 1.当n=1或n=2时,青蛙跳台阶跳法次数和没修改条件时是一样的,n=1有一种跳法,n=2有两种跳法。 2.当n>2时,同理我们将青蛙跳n级台阶时的跳法记成函数f(n)。但是青蛙在第一次的选择不仅仅是跳1级和跳2级,它还可以选择跳3,4,5,...,n级。所以青蛙跳一次后还会剩n-1,n-2,n-3,...,2, 1, 0级台阶。 此时,f(n)=f(n-1)+f(n-2)+f(n-3)+...+f(2)+f(1)+1 同理,f(n-1)=f(n-2)+f(n-3)+f(n-4)+...+f(2)+f(1)+1 合并上面两个式子得,f(n)=2*f(n-1) 3.根据2的推论得出一个等比数列,由此我们还可以进一步推导: 🍁推导1:f(n)=f(n-1)+f(n-2)+f(n-3)+...+f(2)+f(1)+1 =1+f(1)+f(2)+...+f(n-2)+f(n-1) =1+2^0^*f(1)+2^1^*f(1)+...+2^n-3^*f(1)+2^n-2^*f(1) =1+(2^0^+2^1^+2^2^+...+2^n-3^+2^n-2^) =1+(2^n-1^-1) =2^n-1^ f(1) = 1,f(2) = 2,f(n)为公比的2的等比数列(n>2) 🍁推导2:f(1) = 2^0^, f(2) = 2^1^, f(3) = 2^2^......, f(n-1) = 2^n-2^, f(n) = 2^n-1^

🍧3.2.2代码演示

public class testBlog {
    //frog1递归,frog2迭代
    public static int frog1(int  n) {
        if (n <= 2) {
            return n;
        }
        return frog1(n - 1) + frog1(n - 2);
    }
    public static int frog2(int n) {
        if (n == 1 || n == 2) {
            return n;
        }
        int f1 = 1;
        int f2 = 2;
        int fn = 0;
        while (n - 2 != 0) {
            fn = f1 + f2;
            f1 = f2;
            f2 = fn;
            n--;
        }
        return fn;
    }
    public static int frogPlus1(int n) {
        if (n == 1) {
            return n;
        }
        return 2 * frogPlus1(n - 1);
    }
    public static int frogPlus2(int n) {
        if (n == 1) {
            return n;
        }
        int f1 = 1;
        int fn = 0;
        while (n - 1 != 0) {
            fn = 2 * f1;
            f1 = fn;
            n--;
        }
        return fn;
    }
    public static int frogPlus3(int n) {
        return (int)Math.pow(2, n - 1);
    }
    public static void main(String[] args) {
        //青蛙跳台阶
        for (int i = 1; i < 13; i++) {
            System.out.print(frog1(i) + "  ");//青蛙跳台阶递归结果
        }
        System.out.println();
        for (int i = 1; i < 13; i++) {
            System.out.print(frog2(i) + "  ");//青蛙跳台阶迭代结果
        }
        System.out.println();
        for (int i = 1; i < 13; i++) {
            System.out.print(frogPlus1(i) + "  ");//青蛙跳台阶变式递归结果
        }
        System.out.println();
        for (int i = 1; i < 13; i++) {
            System.out.print(frogPlus2(i) + "  ");//青蛙跳台阶变式迭代结果
        }
        System.out.println();
        for (int i = 1; i < 13; i++) {
            System.out.print(frogPlus3(i) + "  ");//青蛙跳台阶变式结论结果
        }
    }
}

8

🍦3.3汉诺塔问题

🍧3.3.1问题描述及思路

Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A,B,C。开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个先知想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座。你能帮这位先知实现他的想法吗?要求编程序输出移动盘子的步骤。 🍁解题思路: 这位先知会这样想: 假如有另外一位先知能有办法将上面63个盘子从A座移到B座。那么,问题就解决了。此时先知只须这样做: ① 联系他的好朋友第2个先知将63个盘子从A座移到B座; ② 自己将1个盘子(最底下的、最大的盘子)从A座移到C座; ③ 再让第2个先知将63个盘子从B座移到C座。 第2个先知又想: 如果有人能将62个盘子从一个座移到另一座,我就能将63个盘子从A座移到B座,他是这样做的: ① 联系他的好朋友第3个先知将62个盘子从A座移到C座; ② 自己将1个盘子从A座移到B座; ③ 再让第3个先知将62个盘子从C座移到B座。 …… 以此类推 1 为了便于理解,我们将盘子数量降低到3个,所以首先分析将A座上3个盘子移到C座上的过程: 4

① 将A座上2个盘子移到B座上(借助C座)。

② 将A座上1个盘子移到C座上。

③ 将B座上2个盘子移到C座上(借助A座)。 5

其中第②步可以直接实现。第①步又可用递归方法分解为:

  1. 将A座上1个盘子从A座移到C座;
  2. 将A座上1个盘子从A座移到B座;
  3. 将C座上1个盘子从C座移到B座。

第③步可以分解为:

  1. 将B座上1个盘子从B座移到A座上;
  2. 将B座上1个盘子从B座移到C座上;
  3. 将A座上1个盘子从A座移到C座上。

将以上综合起来,可得到移动3个盘子的步骤为: A→C,A→B,C→B,A→C,B→A,B→C,A→C。 共经历7步。由此可推出: 移动n个盘子要经历(2^n^-1)步。

🍧3.3.2代码演示

🍁由上面的分析可知: 将n个盘子从A座移到C座可以分解为以下3个步骤: ① 将A座上n-1个盘借助C座先移到B座上; ② 把A座上剩下的一个盘移到C座上; ③ 将n-1个盘从B座借助于A座移到C座上。

🍁可以把上面3个步骤分成两类操作: ① 将n-1个盘从一个座移到另一个座上(n>1)。这就是先知让他的朋友第2个先知做的工作,它是一个递归的过程,即先知将任务层层下放,直到第64个先知为止。 ——hanoi函数 ② 将1个盘子从一个座上移到另一座上。这是先知自己做的工作。 ——move函数

public class testBlog {
    public static void move(char m, char n) {
        System.out.println(m + "->" + n);
    }
    public static void hanoi(int num, char a, char b, char c) {
        if (num == 1) {
            move(a, c);
            return;
        }
        hanoi(num - 1, a, c, b);
        move(a, c);
        hanoi(num - 1, b, a, c);
    }
    public static void main(String[] args) {
        //Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A,B,C。
        //开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。
        //有一个先知想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘,
        //且在移动过程中在3个座上都始终保持大盘在下,小盘在上。
        //在移动过程中可以利用B座。你能帮这位先知实现他的想法吗?
        //要求编程序输出移动盘子的步骤。
        int num = 3;
        hanoi(3,'A', 'B', 'C');
    }
}

看看3个盘子的汉诺塔程序是怎么移动的:

99

与我们推演出来的移动顺序一致!

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。