JavaSE面试题——方法的递归与迭代

简介: JavaSE面试题——方法的递归与迭代

1.Go!!!


编程题:n步台阶,每次只能走一步或者走两步,则共有多少种不同的走法?

这个问题了话,我能想到的就是两种方法:1.递归;2.迭代。

这二者的区别在于:方法调用自身称为递归;利用变量的原值推出新值称为迭代。

2.递归


·       n=0:没意义,台阶数不可能小于1

·       n=1:只能走一步直接到位,f(1)=1

·       n=21+12f(2)=2

·       n=31+1+11+22+1f(3)=3 = f(2) + f(1)

·       n=41+1+1+11+2+11+1+22+1+12+2f(4)=5 = f(3) + f(2)

·       n=51+1+1+1+11+2+1+11+1+2+12+1+1+11+1+1+21+2+22+1+22+2+1f(5)=8 = f(4) + f(3)

·       ......

·       n=xf(x) = f(x-1) + f(x-2)


规律已经可以看出来了,从n=3开始,后面的每一项都等于它对应的前两项之和。


这里想说一下,不要说这个就是斐波那契数列,斐波那契数列的前几项是 0112358......,你们学过斐波那契数列吗?和这个一样吗???合适的说法还是类似于斐波那契数列。(不要说这就是斐波那契数列,让别人听了误以为真,忽略了斐波那契数列前面还有两项01,数学的奇妙之处就在于严谨。你也别扯什么这是计算机不是什么数学,你仔细想想计算机是不是基于数学的?它们二者谁先诞生?)

import java.util.Scanner;
/**
 *
 */
public class Step1 {
    public static long f(long n) {
        if (n < 1) {
            throw new IllegalArgumentException("台阶数n不能小于1");
        }
        if (n == 1 || n == 2) {
            return n;
        }
        return f(n-1) + f(n-2);
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long start = System.currentTimeMillis();
        long n = scanner.nextLong();
        System.out.println(f(n));
        long end = System.currentTimeMillis();
        System.out.println("程序运行总耗时: " + (end - start));
    }
}

3.迭代


这里首先我们需要三个临时变量onetworesult,其中one保存的是最后走一步的情况,two保存的是最后走两步的情况,result是最终的结果。


·       n=0:没意义,台阶数不可能小于1

·       n=1:只能走一步直接到位,f(1)=1

·       n=21+12f(2)=2

·       n=3先到达f(1),然后从f(1)直接走两步到达,即此时f(1)=two先到达f(2),然后从f(2)直接走一步到达,即此时f(2)=one;所以f(3)=one + two

·       n=4:当n=3时,two表示最后走两步的情况,而当n=4,台阶数多了一阶,这个时候n=3时的那个one(最后走一步)就变成了最后要走两步,即 two = one


n=3时的那个one表示最后走一步的情况,此时n=4,台阶数多了一阶,这个时候n=3时的那个result(最终结果)就变成了最后要走一步,即 one = result

import java.util.Scanner;
/**
 *
 */
public class Step2 {
    public static long f(long n) {
        if (n < 1) {
            throw new IllegalArgumentException("台阶数n不能小于1");
        }
        if (n == 1 || n == 2) {
            return n;
        }
        long one = 2; //初始化为走到第二级台阶的走法(保存最后走一步)
        long two = 1; //初始化为走到第一级台阶的走法(保存最后走两步)
        long result = 0;
        for (long i = 3; i <= n; i++) {
            //最后走一步 + 最后走两步的走法
            result = one + two;
            two = one;
            one = result;
        }
        return result;
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        long start = System.currentTimeMillis();
        long n = scanner.nextLong();
        System.out.println(f(n));
        long end = System.currentTimeMillis();
        System.out.println("程序运行总耗时: " + (end - start));
    }
}

最终对比递归和迭代来看:


递归:

·       优点:大问题转化为小问题,可以减少代码量,同时代码精简,可读性好。

·       缺点:递归调用浪费了空间,而且递归太深容易造成堆栈的溢出。


迭代:

·       优点:代码运行效率好,因为时间只因循环次数增加而增加,而且没有额外的空间开销。

·       缺点:代码比递归要复杂,同时可读性不如递归。 

相关文章
|
12天前
|
SQL 安全 测试技术
[go 面试] 接口测试的方法与技巧
[go 面试] 接口测试的方法与技巧
|
13天前
|
机器学习/深度学习 算法 Python
【机器学习】面试问答:决策树如何进行剪枝?剪枝的方法有哪些?
文章讨论了决策树的剪枝技术,包括预剪枝和后剪枝的概念、方法以及各自的优缺点。
29 2
|
13天前
|
机器学习/深度学习
【机器学习】面试题:LSTM长短期记忆网络的理解?LSTM是怎么解决梯度消失的问题的?还有哪些其它的解决梯度消失或梯度爆炸的方法?
长短时记忆网络(LSTM)的基本概念、解决梯度消失问题的机制,以及介绍了包括梯度裁剪、改变激活函数、残差结构和Batch Normalization在内的其他方法来解决梯度消失或梯度爆炸问题。
27 2
|
13天前
|
存储 机器学习/深度学习 缓存
【数据挖掘】XGBoost面试题:与GBDT的区别?为什么使用泰勒二阶展开?为什么可以并行训练?为什么快?防止过拟合的方法?如何处理缺失值?
XGBoost与GBDT的区别、XGBoost使用泰勒二阶展开的原因、并行训练的原理、速度优势、防止过拟合的策略以及处理缺失值的方法,突出了XGBoost在提升模型性能和训练效率方面的一系列优化。
17 1
|
14天前
|
机器学习/深度学习
|
12天前
|
运维 监控 算法
[go 面试] 优化线上故障排查与性能问题的方法
[go 面试] 优化线上故障排查与性能问题的方法
|
1月前
|
Android开发
Android面试题之View的invalidate方法和postInvalidate方法有什么区别
本文探讨了Android自定义View中`invalidate()`和`postInvalidate()`的区别。`invalidate()`在UI线程中刷新View,而`postInvalidate()`用于非UI线程,通过消息机制切换到UI线程执行`invalidate()`。源码分析显示,`postInvalidate()`最终调用`ViewRootImpl`的`dispatchInvalidateDelayed`,通过Handler发送消息到UI线程执行刷新。
27 1
|
17天前
|
JavaScript
给原始数据类型加属性和方法为什么不会报错?包装类——阿里面试题
给原始数据类型加属性和方法为什么不会报错?包装类——阿里面试题
|
1月前
|
缓存 Prometheus 监控
Java面试题:如何监控和优化JVM的内存使用?详细讲解内存调优的几种方法
Java面试题:如何监控和优化JVM的内存使用?详细讲解内存调优的几种方法
53 3
|
26天前
|
消息中间件 调度 Android开发
Android经典面试题之View的post方法和Handler的post方法有什么区别?
本文对比了Android开发中`View.post`与`Handler.post`的使用。`View.post`将任务加入视图关联的消息队列,在视图布局后执行,适合视图操作。`Handler.post`更通用,可调度至特定Handler的线程,不仅限于视图任务。选择方法取决于具体需求和上下文。
27 0