首页 > 其他分享 >【LeetCode 509 】斐波那契数

【LeetCode 509 】斐波那契数

时间:2024-03-23 13:22:55浏览次数:25  
标签:契数 begin end int res 斐波 base pmatrix LeetCode

题目描述

原题链接: LeetCode.0509 斐波那契数

解题思路

  • 题目直接给出了公式, 朴素解法可以直接用\(O(n)\)复杂度求出答案, 可以看做是递归或动态规划的入门题;
  • 这里重点作为模板题来介绍矩阵快速幂技巧, 讲一下\(O(log_2n)\)复杂度的解法:
    • 递推公式\(F(n)=F(n-1)+F(n-2)\), 转换为矩阵形式为: \(\begin{pmatrix}F_{n-1} & F_{n-2}\end{pmatrix}*\begin{pmatrix}a_1 & a_2\\b_1 & b_2\end{pmatrix} = \begin{pmatrix}F_n & F_{n-1}\end{pmatrix}\), 要想求得\(F_n\)就求得\(\begin{pmatrix}F_2&F_1\end{pmatrix}\)乘以\(\begin{pmatrix}a_1&a_2\\b_1&b_2\end{pmatrix}^{n-2}\)的结果。
    • 代入\(F_0=0, F_1=1, F_2=1, F_3=2\)可得方程组:

    \[\begin{cases} 1*a_1+0*b_1=1\\ 1*a_2+0*b_2=1\\ 1*a_1+1*b_1=2\\ 1*a_2+1*b_2=1 \end{cases} => \begin{cases} a_1=1\\ a_2=1\\ a_1+b_1=2\\ a_2+b_2=1 \end{cases} \]

    • 求得递推矩阵为: \(\begin{pmatrix}1&1\\1&0\end{pmatrix}\)。

解题代码

  • 朴素动态规划版本:

      /**
       * 最朴素动态规划
       * 执行用时: 0 ms , 在所有 Java 提交中击败了 100.00% 的用户
       * 内存消耗: 38.1 MB , 在所有 Java 提交中击败了 70.11% 的用户
       */
      public int fib(int n) {
          if (n < 2) {
              return n;
          }
          // 定义数组是为了直观, 也可以用三个变量滚动求解
          int[] dp = new int[n + 1];
          dp[1] = 1;
          for (int i = 2; i <= n; i++) {
              dp[i] = dp[i - 1] + dp[i - 2];
          }
          return dp[n];
      }
    
  • 基于递推矩阵的快速幂解法:

      /**
       * 矩阵快速幂技巧
       * 执行用时: 0 ms , 在所有 Java 提交中击败了 100.00% 的用户
       * 内存消耗: 39.39 MB , 在所有 Java 提交中击败了 35.84% 的用户
       */
      public int fib(int n) {
          if (n < 2) {
              return n;
          }
          int[][] transfer = {{1, 1}, {1, 0}};
          int[][] start = {{1,1}};
          int[][] res = matrixMultiply(start, matrixPower(transfer, n - 2));
          return res[0][0];
      }
    
      private int[][] matrixPower(int[][] base, int n) {
          int row = base.length;
          int[][] res = new int[row][row];
          for (int i = 0; i < row; i++) {
              res[i][i] = 1;
          }
          while (n > 0) {
              if ((n & 1) == 1) {
                  res = matrixMultiply(res, base);
              }
              base = matrixMultiply(base, base);
              n >>= 1;
          }
          return res;
      }
    
      private int[][] matrixMultiply(int[][] a, int[][] b) {
          int m = a.length, n = b[0].length;
          int k = b.length;
          int[][] res = new int[m][n];
          for (int aRow = 0; aRow < m; aRow++) {
              for (int bCol = 0; bCol < n; bCol++) {
                  for (int i = 0; i < k; i++) {
                      res[aRow][bCol] += a[aRow][i] * b[i][bCol];
                  }
              }
          }
          return res;
      }
    

标签:契数,begin,end,int,res,斐波,base,pmatrix,LeetCode
From: https://www.cnblogs.com/coding-memory/p/18091007

相关文章

  • (Java)猛刷LeetCode——数组知识点篇
    数组Array在连续的内存空间中,存储一组相同类型的元素元素:值索引:数组的下标数组访问(Access)和数组搜索(Search)●数组访问:索引●数组搜索:找2这个元素数组中有没有以下是数组的常规操作:数组创建、添加元素、访问元素、修改元素、删除元素、遍历数组、查找元素、数组......
  • LeetCode题练习与总结:接雨水
    一、题目给定 n个非负整数表示每个宽度为1的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。示例1:输入:height=[0,1,0,2,1,0,1,3,2,1,2,1]输出:6解释:上面是由数组[0,1,0,2,1,0,1,3,2,1,2,1]表示的高度图,在这种情况下,可以接6个单位的雨水(蓝色部分表示雨......
  • LeetCode题练习与总结:缺失的第一个正数
    一、题目给你一个未排序的整数数组nums,请你找出其中没有出现的最小的正整数。请你实现时间复杂度为O(n)并且只使用常数级别额外空间的解决方案。二、解题思路遍历数组:首先,我们需要遍历数组,找到所有负数和零,并将它们替换为一个特定的值(比如数组的最大值加一),这样我们就......
  • LeetCode 55.跳跃游戏
    题目:方法一:给定数组中,每一位都可以确定出他所能跳到的最远距离(nums[i]+i)当然,前提是当前该位能够由前面的位置跳到我们可以定义一个总的最远距离(maxdistance)来记录(最远距离:当前能够到达的最大下标值)如果当前位置能够被跳到且其所能跳到的最远距离大于maxdistance,那么更新......
  • LeetCode刷题记录——day4
    https://leetcode.cn/problems/trapping-rain-water/description/?envType=study-plan-v2&envId=top-interview-150对于一个可以构成“碗”的序列,最后装满水的话应该和最短的一边齐平,那么可以左右各遍历一次,记录每个元素位置对应的最短边高度,再对比就可以得出左右哪边最短class......
  • 【LeetCode-153.寻找旋转排序数组的最小值】
    已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums=[0,1,2,4,5,6,7] 在变化后可能得到:若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]注意,数组 [a[0],a[1],a[2],...,a[n-1......
  • 算法打卡day25|回溯法篇05|Leetcode 491.递增子序列、46.全排列、47.全排列 II
     算法题Leetcode491.递增子序列题目链接:491.递增子序列大佬视频讲解:递增子序列视频讲解 个人思路和昨天的子集2有点像,但昨天的题是通过排序,再加一个标记数组来达到去重的目的。而本题求自增子序列,是不能对原数组进行排序的,因为排完序的数组都是自增子序列了。解决......
  • 【C++ leetcode】双指针问题
    1.  611.有效三角形的个数题目给定一个包含非负整数的数组nums,返回其中可以组成三角形三条边的三元组个数。题目链接.-力扣(LeetCode)画图和文字分析判断是否是三角形要得到三边,由于遍历三边要套三层循环,时间复杂度很大,所以这里我们需要借助双指针思想,可......
  • leetcode148. 排序链表-归并法
    148.排序链表题干给你链表的头结点head,请将其按升序排列并返回排序后的链表。示例1:输入:head=[4,2,1,3]输出:[1,2,3,4]示例2:输入:head=[-1,5,3,4,0]输出:[-1,0,3,4,5]示例3:输入:head=[]输出:[]提示:链表中节点的数目在范围[0,5*104]内-105<=N......
  • Leetcode 多数元素
    Day8第一题解题思路:数组中的数a出现次数若超过n/2,则排序后处于中间位置的元素一定是a。importjava.util.*;classSolution{publicintmajorityElement(int[]nums){//如果他超过n/2,则排序后处于中间位置。intn=nums.length;Arrays.......