斐波那契数列Kotlin的N种实现方式

Kotlin算法面试宝典:核心问题与高效实现 算法是计算机科学的基础,掌握常见数据结构与算法原理是开发者必备技能。从数组操作到图遍历,算法通过优化时间复杂度和空间复杂度来提升程序性能。在JVM生态中,Kotlin凭借扩展函数、高阶函数等特性,能以更简洁的代码实现经典算法。本文以排序算法、动态规划等高频面试题为切入点,详解如何利用Kotlin语言特性优化算法实现,包括使用序列(Sequence)进行惰性求值、inline函数减少内存开销等技巧,帮助开发者在技术面试中展现扎实的算法功底和语言运用能力。 阅读详情

前言

半年前开始接触和学习Kotlin,最近看完了两本Kotlin的书,我对Kotlin的看法是这样的:有点东西 -> 唉哟不错 -> 卧槽牛批。

虽然说是有一定的学习成本在那里,但是还是很值得的,思维和效率比起Java,提高的不是一点,而且未来如果Compose有幸占据主流的话,安卓开发Kotlin是必备技能了。对安卓开发感兴趣并想要持续深入的同学,抓紧学起来吧!

背景

网上看到很多斐波那契数列的各种语言版本,花里胡哨的亚子,但感觉不够且凑数(比如while循环和for循环,就算两种了吗 #手动狗头#),于是就心血来潮自己尝试用Kotlin写几种实现方式(PS: 最后要得到数列对象,简单的一个个打印出来不算)

Fibonacci数列定义

*斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89...
这个数列从第3项开始,每一项都等于前两项之和。*

												——来自百度百科

Kotlin编程实现

明确要求:

  1. 输出一个含斐波那契数列的List对象,并打印List,不能是简单的过程打印
  2. 测量计算过程的时间,并打印时间
  3. 正常情况下,要计算斐波那契数列到第100位,并打印位数(普通递归方式计算到30位)

1. 简单循环方式

1.1. for循环区间

当然也可以循环列表等,也可以用while循环,原理类似,就不列举了

	fun fibonacci1_1() {
        measureNanoTime {
            val list = mutableListOf<BigInteger>()
            var x = BigInteger.ONE
            var y = BigInteger.ONE
            var z: BigInteger

            for (i in 1..100) {
                list.add(x)
                z = x
                x = y
                y += z
            }
            println("list = $list")
            println("size = ${list.size}")
        }.also{ println("cost time = $it Nano") }
    }

结果:
结果1.1
这里花费了3,944,200纳秒的时间,也就是3.9毫秒,其实是非常快的

1.2. 使用kotlin的标准函数also,简化写法

这样的好处是不用创建临时变量z来保存x了,代码简洁些,但是测试了几次发现好像是会稍微耗费多一点时间,不确定是不是其他原因

    fun fibonacci1_2() {
        measureNanoTime {
            val list = mutableListOf<BigInteger>()
            var x = BigInteger.ONE
            var y = BigInteger.ONE

            for (i in 1..100) {
                list.add(x)
                x = y.also { y += x }
            }
            println("list = $list")
            println("size = ${list.size}")
        }.also{ println("cost time = $it Nano") }
    }

结果:
结果1.2
花费了6毫秒,也挺快了

2. 递归方式

2.1 普通递归

简单递归是Fibonacci数列最常见的方式,它是根据Fibonacci数列的通项式演变来的,如下:
通项式
看代码:

    private fun fib(n: Int): BigInteger =
        when (n) {
            1 -> BigInteger.ONE
            2 -> BigInteger.ONE
            else -> fib(n - 1) + fib(n - 2)
        }


    @Test
    fun fibonacci2_1() {
        measureNanoTime{
            val list = mutableListOf<BigInteger>()
            for (i in 1..30) {
                list.add(fib(i))
            }
            println("list = $list")
            println("size = ${list.size}")
        }.also { println("cost time = $it Nano") }
    }

结果:
结果2.1
可以看到才计算30位,但是花了104毫秒,比前面的循环法计算100位都满,而且普通递归法耗时呈指数增长,调用基数稍大还会有内存溢出风险

2.2 尾递归优化

kotlin支持尾递归优化,专门解决上述普通递归的痛点,关键字:tailrec
使用尾递归优化,函数的最后必须有调用自身,所以这里我们要做一些调整
看代码:

	private tailrec fun fib_tail(
        x: BigInteger = BigInteger.ONE,
        y: BigInteger = BigInteger.ONE,
        count: Int = 100,
        list: MutableList<BigInteger> = mutableListOf()
    ): List<BigInteger> {
        return if (count > 0) {
            fib_tail(y, x + y, count - 1, list.apply { add(x) })
        } else {
            list
        }
    }
    
	@Test
    fun fibonacci2_2() {
        measureNanoTime {
            fib_tail().also {
                println("list = $it")
                println("size = ${it.size}")
            }
        }.also { println("cost time = $it") }
    }

结果:
结果2.2
可以看到,经过尾递归优化后,计算到第100位所用的时间和我们之前使用循环法差不多,也是4毫秒左右。因为尾递归优化,转成java字节码后可以看到,其实就是编译器帮我们转换成了循环,所以它的效率是和循环方式是差不多的。

3.1 Flow方式

flow是kotlin协程库里的,需要导入以下依赖

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1'

看代码:

    //Flow方式
    fun fib_flow(): Flow<BigInteger> = flow {
        var x = BigInteger.ONE
        var y = BigInteger.ONE
        var z: BigInteger

        while (true) {
            emit(x)
            z = x
            x = y
            y += z
        }
    }

    //调用flow生成数列
    @Test
    fun fibonacci3_1() {
        runBlocking {
            measureNanoTime {
                fib_flow()
                    .take(100)  //计算100次
                    .toList()   //末操作符,在此时才执行和收集Flow
                    .also {
                        println("list = $it")
                        println("size = ${it.size}")
                    }
            }.also { println("cost time = $it") }
        }
    }

结果:
结果3
这里用了14毫秒左右,可还是比较可以的。注意,这里如果把计算时间放在runBlocking作用域外的话,时间会久100多毫秒,因为runBlocking函数会阻塞当前线程。

3.2. 使用also简化

    //Flow方式
    fun fib_flow(): Flow<BigInteger> = flow {
        var x = BigInteger.ONE
        var y = BigInteger.ONE

        while (true) {
            emit(x)
            x = y.also { y += x }
        }
    }

    //调用flow生成数列
    @Test
    fun fibonacci3_1() {
        runBlocking {
            measureNanoTime {
                fib_flow()
                    .take(100)  //计算100次
                    .toList()   //末操作符,在此时才执行和收集Flow
                    .also {
                        println("list = $it")
                        println("size = ${it.size}")
                    }
            }.also { println("cost time = $it") }
        }
    }

结果3.2
可以看到只用了13毫秒左右

Sequence序列方式

Sequence对刚接触kotlin的童鞋可能比较陌生,它和List、set、map等其他的集合类有很大的不同,序列的迭代是逐个元素的迭代,而集合是整个迭代,在一些场景可以大大优化代码效率,例如查找等。

直接看代码:

    //Sequence序列方式
    fun fib_seq(): Sequence<BigInteger> {
        var x = BigInteger.ONE
        var y = BigInteger.ONE

		//生成无限序列
        return generateSequence(BigInteger.ONE) {
            x = y.also { y += x }
            x  //将x放进序列
        }
    }

    @Test
    fun fibonacci4_1(){
        measureNanoTime {
            fib_seq().take(100).toList().also {
                println("list = $it")
                println("size = ${it.size}")
            }
        }.also { println("cost time = $it") }
    }

结果:
结果4
16毫秒左右,也还可以

结论

Kotlin的几种生成斐波那契数列的方式里,最快的是简单的循环方式,与第一几乎并列的是尾递归优化方式,因为它的本质其实也是循环,其次是Flow方式,和Sequence序列方式,他们效率差不多,Flow稍高一些,最差的是普通递归方式,计算30位却用的时间最多。

PS最后发现其实测量计算时间应该排除掉打印List和Size的时间,排除掉之后,差不多相差3毫秒左右,这么一看,循环的效率是真的高,最后我把每个方式计算10000位,并取中间值,整理了个图,更加直观。(单位纳秒)

图表
时间

写在结尾

为了这篇文章,花费了半个周末,还有其他方式或者好的想法,欢迎评论或私信,一起学习进步鸭~
后续有补充的话我再更新

Kotlin算法面试宝典:函数式编程与实战技巧 算法作为程序员的核心能力,在技术面试中占据重要地位。Kotlin作为现代JVM语言,凭借其函数式编程特性和丰富的集合操作API,为算法实现提供了独特优势。理解基础数据结构如数组、链表、哈希表的实现原理,掌握双指针、回溯、动态规划等算法模式,是解决复杂问题的关键。Kotlin的扩展函数、序列惰性求值和协程支持等特性,能够显著提升算法代码的可读性和执行效率。在面试场景中,合理运用Kotlin的when表达式、作用域函数和空安全机制,可以编写出既简洁又健壮的算法实现。本文通过典型算法题的Kotlin解决方案,展示 阅读详情

相关推荐

Kotlin算法面试宝典:30个核心问题解析与优化技巧

算法是编程面试的核心考察点,而Kotlin作为现代JVM语言,其简洁语法和丰富标准库为算法实现提供了独特优势。理解数据结构与算法原理是基础,Kotlin的集合操作符如map、filter等能简化代码,但需注意其空间复杂度。在实际工程中,算法优化常涉及时间空间权衡,Kotlin的特性如内联函数、尾递归等能有效提升性能。本专题聚焦Kotlin程序员面试中的30个高频算法问题,涵盖字符串处理、动态规划等场景,特别解析如何利用Kotlin空安全、协程等特性写出既优雅又高效的算法实现,帮助开发者在技术面试中脱颖而出。

weixin_34021089的博客 341

斐波那契数列

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下: F(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回...

weixin_42738495的博客 670

Kotlin算法面试宝典:从基础到高阶实战技巧

算法作为程序员的核心能力,直接影响着问题解决效率与系统性能。从基础的排序、搜索到高级的动态规划,算法思维帮助开发者高效处理数据结构和复杂逻辑。在Android开发领域,Kotlin凭借其简洁语法和现代特性,成为实现算法的理想选择。通过扩展函数、协程并发等特性,开发者可以用更少的代码实现经典算法如快速排序、二叉树遍历。特别是在技术面试场景中,掌握Kotlin风格的算法实现能显著提升代码表现力,同时算法优化技巧如记忆化、内联函数等对性能敏感场景尤为重要。本指南聚焦Kotlin与算法面试的结合,涵盖从基础数据结构

weixin_33796205的博客 357

关于斐波那契数列的优化

斐波那契数列的优化

大呆_的博客 5089

【禅与计算机程序设计艺术】使用 16 门编程语言实现斐波那契数列:循环控制指令与函数递归思想

斐波那契数列又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……。斐波那契数列的特点是数列的前两个数都是1,从第三个数开始,每个数都是它前面两个数的和。在 Kotlin 语言中,可以使用循环和递归两种方式来实现斐波那契数列,使用循环实现时,首先判断输入的参数是否是1或者2,如果是,则返回1;否则,就使用循环的方式来求解斐波那契数列。使用递归实现时,也是使用 if-else 语句来求解斐波那契数列,如果输入的参数是1或者2,则返回1;

AI天才研究院 2万+

fibonacci_app:基本的斐波那契应用程序来练习更多的 Android 开发

fibonacci_app 用于练习更多 Android 开发的基本斐波那契应用程序。

2018安卓面试经历

首先声明一下,以下部分答案是我自己答得,有不对的地方,大家可以在评论区改正,共同成长。多点面试题1、解决大图片加载卡顿问题    先使用默认图占位,加载小图 然后再加载大图 2、长图压缩3、经纬度 实时定位 耗电  为什么不在某一时刻 去请求位置  经纬度是真的吗  百度和高德怎么转换4、版本更新为什么使用服务 没有直接下载  当时使用服务 是在服务中开启的子线程下载,然后将为了将进度发送的通知栏...

lzq520210的博客 8961

android 斐波那契数列(jni)

列表从0开始,从小到大,每行显示一个斐波那契数字 列表的第n行显示F(n3),至少显示到 F(603) android C++

android5.1断点续传,5.1.7 07.斐波那契数列 - Android 校招面试指南

一、题目写一个函数,输入n,求斐波那契数列的第n项值。斐波那契数列的定义如下:二、解题思路按照上述递推式,可以使用循环或递归的方式获取第n项式。三、解题代码public class Test {/*** 写一个函数,输入n,求斐波那契(Fibonacci) 数列的第n项* @param n Fibonacci数的项数* @return 第n项的结果*/public static long fibo...

weixin_30513765的博客 159

【全网最新】使用 1panel面板 部署若依系统( springboot 和 vue)项目

打开前端项目的vue.config.js文件,检查devServer下的proxy代理部分,然后将下面这个端口修改为你要在打包后访问的端口,即使用nginx代理前的接口。这个端口默认是80端口,这里把其修改为不会冲突的8010端口,后台接口的地址配置为9080,不过感觉这里设置的8010和9080可能没有用,因为部署前端静态页面是,也配置了一次网页的外部接口和api的接口,后期有空了再验证。打开右侧的Maven,点击:生存期->package,然后点击运行,等待打包成功,包在如图所示的文件夹中。

老薛的专栏 1754

【OCCT】第3讲 OpenCasCade&VTK实现三维建模Demo

本文分享OpenCasCade&VTK共同实现三维建模Demo,希望对各位小伙伴有所帮助!1. 新建Visual Studio工程新建空项目添加main.cpp添加main函数2. 配置OpenCasCade & VTK 库配置包含路径:配置库文件:添加链接库:添加运行环境:注意:VTK库的版本要与编译OpenCasCade库时选择的版本一致,否则会出错!

qq_40041064的博客 779

kotlin 程序入口_Kotlin程序将展示斐波那契数列

kotlin 程序入口In mathematics, the Fibonacci series is the series of the numbers where each number is the sum of the two preceding numbers, starting from 0 and 1. 在数学中, 斐波那契数列是数字的序列,其中每个数字是从0和1开始的两个先前数字的...

452

FPGA实战:MIG IP核AXI接口DDR3读写优化指南

本文详细解析了FPGA中MIG IP核AXI接口的DDR3读写优化策略,涵盖关键参数配置、突发传输技巧及时序收敛方案。通过AXI接口优化和突发长度选择,可实现高达12.8GB/s的理论带宽,提升DDR3访问效率。文章还提供了Vivado配置实例和调试技巧,助力开发者解决FPGA内存控制中的实际问题。

weixin_29168393的博客 545

斐波那契数列引发的思考 Kotlin

描述:编写程序并输出斐波那契数列前100项。 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1...

Chase1998的博客 816

从频谱分析到硬件加速:用ZYNQ-7020+FFT IP核实现实时信号处理的完整方案

本文详细介绍了如何利用ZYNQ-7020和FFT IP核实现实时信号处理的完整方案,涵盖系统架构设计、硬件加速实现及性能优化。通过异构计算架构,该方案将1024点FFT处理延迟压缩至28μs,显著提升工业自动化和无线通信等领域的实时频谱分析效率。

weixin_33704234的博客 467

【CT/电镜 重建教程 1.1】层析成像的精确实空间迭代重建算法(RESIRE)

在此,我们报告了RESIRE算法的发展用于准确的断层重建。与实空间迭代算法相比,RESIRE使用傅里叶切片定理或Radon变换作为正向投影,使用线性变换作为反向投影,两者都具有高精度。与EST和GENFIRE相比,RESIRE是一种实空间迭代算法,可以在并行计算中实现快速运行时间。

2401_87064292的博客 1060

算法--斐波那契数列(Kotlin)

1.取模这里还是没有思考明白数字太大相加可能会导致溢出int范围为负数所以一定要清楚2.斐波那契数列真的是动态规划的鼻祖。

男儿不展风云志,空有天生八尺躯 474

从 Chat 提示词到可运行 Fiori 应用,ADT for VS Code 正在把 RAP 开发带进 Agent 时代

本文探讨了在VS Code中使用AI辅助进行ABAP RAP开发的新模式。文章指出,传统RAP开发需要手工创建数据库表、CDS视图、行为定义等十多个关联对象,命名和关联关系容易出错。现在通过GitHub Copilot Agent Mode配合ADT MCP Server,开发者可用自然语言描述业务场景直接生成完整的RAP业务对象。这种生成式开发的核心价值在于:1)通过标准化工具接口(MCP)连接ABAP后端,确保生成符合规范的RAP对象;2)能正确处理多实体组合场景下的命名一致性和关联关系;3)保持生成结

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 85

kmp openharmony 斐波那契数列生成器

斐波那契数列生成器是基于Kotlin Multiplatform和OpenHarmony开发的工具,提供按数量、按上限和按索引三种生成模式。该工具采用高效的迭代算法(时间复杂度O(n)),支持展示计算过程和黄金比例分析(相邻项比值趋近1.618)。作为经典算法案例,它适用于算法教学、数学建模、性能测试等多个场景,具有递归、动态规划等多种实现方式,并能直观展示数列特性与数学规律。

2402_88159298的博客 797

华为OD机考双机位C卷 - 斗地主之顺子 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 斗地主之顺子(OD上机考试双机位C卷)。提供在线OJ刷题。Java、C++、Python、GO语言、C语言、JavaScript题解,并提供完整思路讲解。

算法大师! 9692

【STK】手把手教你利用STK进行光电红外仿真03-STK/EOIR模块属性之二 导弹等目标的EOIR设置

上一节介绍了如何设置传感器的通用属性和空间、光学、光谱、辐射四种专项属性。这一节介绍如果对导弹等目标的EOIR属性进行修改。

weixin_44184852的博客 2203

KMP & OpenHarmony 实现斐波那契

本文介绍了如何使用Kotlin Multiplatform(KMP)实现斐波那契数列算法,并将其编译为JavaScript后在OpenHarmony应用中调用。文章详细阐述了算法原理,包括动态规划的实现方式(O(n)时间复杂度),并提供了Kotlin代码示例。通过@JsExport注解将函数导出为JavaScript,编译后可在OpenHarmony应用中执行。文中还包含完整的测试步骤、预期输出、性能分析及优化建议,展示了KMP与OpenHarmony结合实现跨平台算法调用的完整流程。

2501_94450102的博客 847

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

LeetCode之Fibonacci Number(Kotlin)

问题: The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is, F(0) = 0,...

weixin_34227447的博客 169

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

509. 斐波那契数(每日一题)

lzyprime 博客 (github) 创建时间:2021.01.04 qq及邮箱:2383518170 leetcode 笔记 题目描述 斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1 给你 n ,请计算 F(n) 。 示例 1: 输入:2 输出:1 解释:F(2) = F(1) + F(0.

prime的博客 184

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Kotlin·递归与尾递归优化

Kotlin递归与尾递归 文章目录Kotlin递归与尾递归递归概念用途运用缺点尾递归优化概念 递归 概念 简单的来说递归就是一个函数直接或间接地调用自身,是为直接或间接递归。 用途 数据的定义是按递归定义的。(Fibonacci函数,n的阶乘) 问题解法按递归实现。(回溯) 数据的结构形式是按递归定义的。(二叉树的遍历,图的搜索) 运用 // 阶乘 fun factorial(x: Int...

大胡子康贝勒爷 590

LeetCode之All Possible Full Binary Trees(Kotlin)

问题: A full binary tree is a binary tree where each node has exactly 0 or 2 children. Return a list of all possible full binary trees with N nodes. Each element of the answer is the root node of one ...

weixin_33919941的博客 93
上一篇: Could not write standard input to Gradle Test Executor x.问题解决记录
下一篇: Android主流架构心得总结 MVC\MVP\MVVM\MVI
LiePy
博客等级 码龄7年 1927粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值