【LeetCode】剑指 Offer 10- I. 斐波那契数列 p74 -- Java Version

news2024/12/23 14:24:56

题目链接

1. 题目介绍()

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:

  • F(0) = 0, F(1) = 1
  • F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

【测试用例】:
示例 1:

输入:n = 2
输出:1

示例 2:

输入:n = 5
输出:5

【条件约束】:

提示:

  • 0 <= n <= 100

2. 题解

2.1 递归实现 — O(2n)

时间复杂度O(2n),空间复杂度O(1)

class Solution {
    // 第一种方法:递归实现
    public int fib(int n) {
        // 1. n为0时,返回0
        if (n == 0) return 0;
        // 2. n为1时,返回1
        else if (n == 1) return 1;
        // 3. 从第三个数开始,之后的每个数都为前两项数的和
        else return fib(n-1) + fib(n-2);
    }
}

在这里插入图片描述
改进: 使用数组保存每一次的运算结果;改进之后时间复杂度: 从2的n次方降为了O(n²),空间复杂度:O(n)。

class Solution {
    int[] ints;
    
    public int fib(int n) {
        ints = new int[n];
        if(n <= 1) return n;
        return (f(n - 1) + f(n - 2)) % 1000000007;
    }
    private int f(int n) {
        if(n == 0 || n == 1) return n;
        if (ints[n] != 0){
            return ints[n];
        }
        ints[n] = (f(n - 1) + f(n - 2)) % 1000000007;
        return (f(n - 1) + f(n - 2)) % 1000000007;
    }
}

在这里插入图片描述

2.2 滚动数组循环实现

时间复杂度O(n),空间复杂度O(1)
在这里插入图片描述
数组不断滚动向后,逐次累加

class Solution {
    // 第二种方法:循环实现
    public int fib(int n) {
        final int MOD = 1000000007;
        // 1. 定义辅助数组res,用以记录当前值的前两项值
        long[] res = {0,1};
        // 2. 如果n小于2,直接返回
        if (n < 2){
            return (int)res[n];
        } 
        // 3. 定义sum,用于记录从第三项开始,所得到的前两项加和
        long sum  = 0;
        for (int i = 2; i <= n; i++){    
            // 4. sum为前两项加和,然后依次交换元素,逐次相加
            sum = (res[0] + res[1]) % MOD;
            res[0] = res[1];
            res[1] = sum;
        }
        return (int)sum;
    }
}

在这里插入图片描述

2.3 矩阵快速幂 – O(logn)

时间复杂度O(logn),空间复杂度O(1)
在这里插入图片描述
这就涉及到了斐波那契数列的数学公式。

快速幂算法原理: 如需求数据 a 的幂次,此处 a 可以为数也可以为矩阵,常规做法需要对a进行不断的乘积即 a * a * a * …

以求 3^10 的结果为例:
[优化步骤1:]
易知:
3^10=3*3*3*3*3*3*3*3*3*3
=9^5 = 9^4*9
=81^2*9
=6561*9

基于以上原理,我们在计算一个数的多次幂时,可以先判断其幂次的奇偶性,然后:

  • 如果幂次为偶直接 base(底数) 作平方,power(幂次) 除以2

  • 如果幂次为奇则底数平方,幂次整除于2然后再多乘一次底数

[优化步骤2:]

对于以上涉及到 [判断奇偶性] 和 [除以2] 这样的操作。使用系统的位运算比普通运算的效率是高的,因此可以进一步优化:

  • 把 power % 2 == 1 变为 (power & 1) == 1

  • 把 power = power / 2 变为 power = power >> 1

class Solution {
    static final int MOD = 1000000007;
    public int fib(int n) {
        //矩阵快速幂
        if (n < 2) {
            return n;
        }
        //定义乘积底数
        int[][] base = {{1, 1}, {1, 0}};
        //定义幂次
        int power = n - 1;
        int[][] ans = calc(base, power);
        //按照公式,返回的是两行一列矩阵的第一个数
        return ans[0][0];
    }

    //定义函数,求底数为 base 幂次为 power 的结果
    public int[][] calc(int[][] base, int power) {
        //定义变量,存储计算结果,此次定义为单位阵
        int[][] res = {{1, 0}, {0, 1}};

        //可以一直对幂次进行整除
        while (power > 0) {
            //1.若为奇数,需多乘一次 base
            //2.若power除到1,乘积后得到res
            //此处使用位运算在于效率高
            if ((power & 1) == 1) {
                res = mul(res, base);
            }
            //不管幂次是奇还是偶,整除的结果是一样的如 5/2 和 4/2
            //此处使用位运算在于效率高
            power = power >> 1;
            base = mul(base, base);
        }
        return res;
    }

    //定义函数,求二维矩阵:两矩阵 a, b 的乘积
    public int[][] mul(int[][] a, int[][] b) {
        int[][] c = new int[2][2];
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                //矩阵乘积对应关系,自己举例演算一遍便可找到规律
                c[i][j] = (int) (((long) a[i][0] * b[0][j] + (long) a[i][1] * b[1][j]) % MOD);
            }
        }
        return c;
    }
}

在这里插入图片描述

3. 参考资料

[1] 一题解带你走进递归和动态规划算法的大门 – 递归改进代码来源
[2] 斐波那契数列(力扣官方题解)-- (Comment 腌菜读作梦想) – 矩阵快速幂解法来源

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/360853.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

修复 K8s SSL/TLS 漏洞(CVE-2016-2183)指南

作者&#xff1a;老 Z&#xff0c;中电信数智科技有限公司山东分公司运维架构师&#xff0c;云原生爱好者&#xff0c;目前专注于云原生运维&#xff0c;云原生领域技术栈涉及 Kubernetes、KubeSphere、DevOps、OpenStack、Ansible 等。 前言 测试服务器配置 主机名IPCPU内存系…

模电中的负反馈

文章目录一、反馈是什么&#xff1f;二、负反馈对于放大性能的影响1.负反馈的作用三、正反馈总结– 一、反馈是什么&#xff1f; 反馈的定义&#xff1a;凡是将放大电路输出端信号&#xff08;电压或电流&#xff09;的一部分或者全部引回到输入端&#xff0c;与输入信号叠加…

【C语言】宏

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;> c语言学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是…

打造Ai作图studio需要哪些工具

这篇文章依然是比较轻松的方式跟大家介绍Ai生成会使用到的一些工具&#xff0c;希望这些工具可以帮助到你更好的更稳定的快捷的生成高质量图片。说来轻松其实也不算轻松&#xff0c;虽然我已经按照生成的链路对工具做了规整。但是里面涉及到的工具其实确实不算少&#xff0c;并…

2023-02-20 Qt 5.13.1 + OpenCV 4.5.4环境编译

引言 OpenCV图像处理在Qt中编译记录。 之前一直是在Python中使用OpenCV&#xff0c;Python中使用某些模块使用pip工具很容易将对应的模块安装在系统中。根据项目需求项目都要转移在国产化中使用&#xff0c;为了适应国产化需求&#xff0c;将代码转移到Qt开发环境中&#xff0c…

django项目实战四(django+bootstrap实现增删改查)进阶时间控件

接上一篇《django项目实战三&#xff08;djangobootstrap实现增删改查&#xff09;进阶分页》 知识点&#xff1a; 使用bootstrap-datepicker实现时间控件 一、优化layout.html模版 主要新增2个块 {% block css %}{% endblock %}{% block js %}{% endblock %} {% load static…

nginx.conf配置方法详细介绍

从前面的内容学习中&#xff0c;我们知道Nginx的核心配置文件默认是放在/usr/local/nginx/conf/nginx.conf&#xff0c;这一节&#xff0c;我们就来学习下nginx.conf的内容和基本配置方法。读取Nginx自带的Nginx配置文件&#xff0c;我们将其中的注释部分【学习一个技术点就是在…

第20讲:Python列表、元组、字符串使用自定义排序规则

文章目录1.自定义排序方法2.常用作自定义排序的函数、方法3.列表、元组、字符串自定义排序方法3.1.当列表、元组中元素为字符串的排序规则3.2.三者采用str.lower方法实现自定义排序3.2.三者采用len函数实现自定义排序1.自定义排序方法 列表、元组、字符串都可以进行排序&#…

友元的学习

&#x1f601;友元的简介类的主要特点之一是数据隐藏&#xff0c;即类的私有成员无法在类的外部作用域之外访问&#xff0c;但是&#xff0c;有时候需要在类的外部访问类的私有成员&#xff0c;这个时候就需要使用友元函数。友元函数是一种特权函数&#xff0c;c允许这哥特权函…

分享在线预约系统制作步骤_在线预约链接怎么做

在微信小程序上进行在线预约&#xff0c;不管是商家还是顾客&#xff0c;都可以自由选择时间&#xff0c;顾客还可以通过预约小程序&#xff0c;了解到所选服务的详情和功能特色&#xff0c;不必等到去店内听介绍&#xff0c;顾客能节省等候时间&#xff0c;商家能解放招待人力…

解决:Vmware Workstation 和 Vmware ESXI 创建虚拟机Ubuntu20.04时界面显示不全,无法点击Continue进行下一步

目录 Vmware Workstation Vmware ESXI Vmware Workstation 1.如下图&#xff0c;到了这一步可以按 CTRL ALT T 调出命令终端 2. 终端输入 xrandr --size 1280x800 此命令是调整屏幕大小 3.此时已经显示屏幕完整信息 Vmware ESXI 安装workstation时那种调整界面大小的方…

每日学术速递2.21

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.T2I-Adapter: Learning Adapters to Dig out More Controllable Ability for Text-to-Image Diffusion Models 标题&#xff1a;T2I-Adapter&#xff1a;学习Adapter&#xff0c;为…

2022年网络安全政策态势分析与2023年立法趋势

近日&#xff0c;公安部第三研究所网络安全法律研究中心与 360 集团法务中心联合共同发布了《全球网络安全政策法律发展年度报告&#xff08;2022&#xff09;》。《报告》概览2022年全球网络安全形势与政策法律态势&#xff0c;并对2023年及后续短期内网络安全政策、立法趋势进…

【微信小程序】原生微信小程序ts模板下引入vant weapp

之前一直是在普通项目下使用 vant weapp&#xff0c;这不最近学了ts&#xff0c;使用微信开发工具的tsless初始化项目&#xff0c;再引入 vant 时踩了好久坑&#xff0c;特来记录一下 前言 本文章适合微信开发工具的ts项目&#xff0c;指的是项目目录结构如下图 总结 从上图…

Leetcode.1401 圆和矩形是否有重叠

题目链接 Leetcode.1401 圆和矩形是否有重叠 Rating &#xff1a; 1709 题目描述 给你一个以 (radius, xCenter, yCenter)表示的圆和一个与坐标轴平行的矩形 (x1, y1, x2, y2)&#xff0c;其中 (x1, y1)是矩形左下角的坐标&#xff0c;而 (x2, y2)是右上角的坐标。 如果圆和矩…

【重点掌握】Java基础之Javaweb核心技术详解

都说一入Java深似海&#xff0c;从此代码是爱人&#xff0c;但是学习的过程却从来都不轻松。当下&#xff0c;越来越多的互联网企业&#xff0c;招聘Java工程师时&#xff0c;明确写道需熟练掌握JavaWeb技术。作为衔接前后端的重要一环&#xff0c;JavaWeb技术已成为程序员向大…

Linux线程调度实验

Linux线程调度实验 1.获取线程属性 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> #include <time.h> #include <stdlib.h> #include <errno.h> #define _GNU_SOURCE#define handle_error…

Power Apps 中判断用户的SharePoint Online Group权限

前言 最近&#xff0c;碰到一个棘手的问题&#xff0c;就是用户有个需求&#xff0c;就是想在Power Apps中判断一个用户是不是在某些AD安全组中。 通常&#xff0c;这样的情况&#xff0c;都需要去AAD中进行判断&#xff0c;判断这个人在不在某些组中&#xff0c;有Graph API可…

双因素方差分析全流程

上篇文章讲述了“单因素方差分析全流程总结”&#xff0c;单因素方差分析只是考虑了一个自变量&#xff08;定类&#xff09;与一个因变量&#xff08;定量&#xff09;之间的关系&#xff0c;但是在实际问题研究中可能研究两个或者几个因素与因变量之间的关系&#xff0c;例如…

监管持续,医疗卫生机构如何守好“涉疫”数据安全?

肆虐三年的新冠疫情&#xff0c;影响着全球经济发展、社会正常运行&#xff0c;也成为网络攻击、勒索软件攻击快速增长的温床&#xff0c;“滋生”了一系列网络、数据安全问题&#xff0c;受到各界关注。最近&#xff0c;上线运行三年的 “粤康码”发布公告、官宣部分服务下线&…