📜  斐波那契数的空间有效迭代法

📅  最后修改于: 2021-05-07 05:47:05             🧑  作者: Mango

给定数字n,找到第n个斐波那契数。请注意,F0 = 0,F1 = 1,F2 = 2,…。

例子 :

Input : n = 5
Output : 5

Input :  n = 10
Output : 89

我们在下面的斐波那契数字程序的方法4中讨论了递归解决方案。

F[2][2] = |1, 1|
          |1, 0|

M[2][2] = |1, 1|
          |1, 0|
F[n][n] = fib(n)  | fib(n-1)
          ------------------
          fib(n-1)| fib(n-2)

在本文中,我们讨论了一种迭代方法,该方法避免了额外的递归调用堆栈空间。我们还使用了按位运算运算符来进一步优化。在前面的方法中,我们将数字除以2,这样最后得到1,然后开始乘法过程
在这种方法中,我们得到第二个MSB,然后开始与FxF矩阵相乘,然后如果设置了位,则再次与FxM矩阵相乘,依此类推。然后我们得到最终结果。

Approach :
1. First get the MSB of a number.
2. while (MSB > 0)
      multiply(F, F);
      if (n & MSB)
      multiply(F, M);
      and then shift MSB till MSB != 0
C++
// CPP code to find nth fibonacci
#include 
using namespace std;
  
// get second MSB
int getMSB(int n)
{
    // consectutively set all the bits
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
  
    // returns the second MSB
    return ((n + 1) >> 2);
}
  
// Multiply function
void multiply(int F[2][2], int M[2][2])
{
    int x = F[0][0] * M[0][0] + F[0][1] * M[1][0];
    int y = F[0][0] * M[0][1] + F[0][1] * M[1][1];
    int z = F[1][0] * M[0][0] + F[1][1] * M[1][0];
    int w = F[1][0] * M[0][1] + F[1][1] * M[1][1];
  
    F[0][0] = x;
    F[0][1] = y;
    F[1][0] = z;
    F[1][1] = w;
}
  
// Function to calculate F[][]
// raise to the power n
void power(int F[2][2], int n)
{
    // Base case
    if (n == 0 || n == 1)
        return;
  
    // take 2D array to store number's
    int M[2][2] = { 1, 1, 1, 0 };
  
    // run loop till MSB > 0
    for (int m = getMSB(n); m; m = m >> 1) {
        multiply(F, F);
  
        if (n & m) {
            multiply(F, M);
        }
    }
}
  
// To return fibonacci numebr
int fib(int n)
{
    int F[2][2] = { { 1, 1 }, { 1, 0 } };
    if (n == 0)
        return 0;
    power(F, n - 1);
    return F[0][0];
}
  
// Driver Code
int main()
{
    // Given n
    int n = 6;
  
    cout << fib(n) << " ";
  
    return 0;
}


Java
// Java code to 
// find nth fibonacci
  
class GFG
{
      
// get second MSB
static int getMSB(int n)
{
    // consectutively set
    // all the bits
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
  
    // returns the
    // second MSB
    return ((n + 1) >> 2);
}
  
// Multiply function
static void multiply(int F[][], 
                     int M[][])
{
    int x = F[0][0] * M[0][0] +
            F[0][1] * M[1][0];
    int y = F[0][0] * M[0][1] +
            F[0][1] * M[1][1];
    int z = F[1][0] * M[0][0] + 
            F[1][1] * M[1][0];
    int w = F[1][0] * M[0][1] + 
            F[1][1] * M[1][1];
  
    F[0][0] = x;
    F[0][1] = y;
    F[1][0] = z;
    F[1][1] = w;
}
  
// Function to calculate F[][]
// raise to the power n
static void power(int F[][], 
                  int n)
{
    // Base case
    if (n == 0 || n == 1)
        return;
  
    // take 2D array to
    // store number's
    int[][] M ={{1, 1}, 
                {1, 0}};
  
    // run loop till MSB > 0
    for (int m = getMSB(n);
             m > 0; m = m >> 1) 
    {
        multiply(F, F);
  
        if ((n & m) > 0) 
        {
            multiply(F, M);
        }
    }
}
  
// To return 
// fibonacci numebr
static int fib(int n)
{
    int[][] F = {{1, 1},    
                 {1, 0}};
    if (n == 0)
        return 0;
    power(F, n - 1);
    return F[0][0];
}
  
// Driver Code
public static void main(String[] args)
{
    // Given n
    int n = 6;
  
    System.out.println(fib(n));
}
}
  
// This code is contributed 
// by mits


Python3
# Python3 code to find nth fibonacci
  
# get second MSB
def getMSB(n):
      
    # consectutively set all the bits
    n |= n >> 1
    n |= n >> 2
    n |= n >> 4
    n |= n >> 8
    n |= n >> 16
  
    # returns the second MSB
    return ((n + 1) >> 2)
  
# Multiply function
def multiply(F, M):
    x = F[0][0] * M[0][0] + F[0][1] * M[1][0]
    y = F[0][0] * M[0][1] + F[0][1] * M[1][1]
    z = F[1][0] * M[0][0] + F[1][1] * M[1][0]
    w = F[1][0] * M[0][1] + F[1][1] * M[1][1]
  
    F[0][0] = x
    F[0][1] = y
    F[1][0] = z
    F[1][1] = w
  
# Function to calculate F[][]
# raise to the power n
def power(F, n):
      
    # Base case
    if (n == 0 or n == 1):
        return
  
    # take 2D array to store number's
    M = [[1, 1], [1, 0]]
  
    # run loop till MSB > 0
    m = getMSB(n)
  
    while m:
        multiply(F, F)
  
        if (n & m):
            multiply(F, M)
  
        m = m >> 1
  
# To return fibonacci numebr
def fib(n):
    F = [[1, 1 ], [1, 0 ]]
    if (n == 0):
        return 0
    power(F, n - 1)
    return F[0][0]
  
# Driver Code
  
# Given n
n = 6
  
print(fib(n))
  
# This code is contributed by Mohit Kumar


C#
// C# code to find nth fibonacci 
using System;
  
class GFG {
      
// get second MSB 
static int getMSB(int n) 
{
      
    // consectutively set 
    // all the bits 
    n |= n >> 1; 
    n |= n >> 2; 
    n |= n >> 4; 
    n |= n >> 8; 
    n |= n >> 16; 
  
    // returns the 
    // second MSB 
    return ((n + 1) >> 2); 
} 
  
// Multiply function 
static void multiply(int [,]F, 
                     int [,]M) 
{ 
      
    int x = F[0,0] * M[0,0] + 
            F[0,1] * M[1,0]; 
    int y = F[0,0] * M[0,1] + 
            F[0,1] * M[1,1]; 
    int z = F[1,0] * M[0,0] + 
            F[1,1] * M[1,0]; 
    int w = F[1,0] * M[0,1] + 
            F[1,1] * M[1,1]; 
  
    F[0,0] = x; 
    F[0,1] = y; 
    F[1,0] = z; 
    F[1,1] = w; 
} 
  
// Function to calculate F[][] 
// raise to the power n 
static void power(int [,]F, 
                    int n) 
{ 
      
    // Base case 
    if (n == 0 || n == 1) 
        return; 
  
    // take 2D array to 
    // store number's 
    int[,] M ={{1, 1}, 
                {1, 0}}; 
  
    // run loop till MSB > 0 
    for (int m = getMSB(n); 
            m > 0; m = m >> 1) 
    { 
        multiply(F, F); 
  
        if ((n & m) > 0) 
        { 
            multiply(F, M); 
        } 
    } 
} 
  
// To return 
// fibonacci numebr 
static int fib(int n) 
{ 
    int[,] F = {{1, 1}, 
                {1, 0}}; 
    if (n == 0) 
        return 0; 
    power(F, n - 1); 
    return F[0,0]; 
} 
  
// Driver Code 
static public void Main ()
{
      
    // Given n 
    int n = 6;
      
    Console.WriteLine(fib(n)); 
} 
} 
  
// This code is contributed ajit


PHP
> 1;
    $n |= $n >> 2;
    $n |= $n >> 4;
    $n |= $n >> 8;
    $n |= $n >> 16;
  
    // returns the second MSB
    return (($n + 1) >> 2);
}
  
// Multiply function
function multiply(&$F, &$M)
{
    $x = $F[0][0] * $M[0][0] + 
         $F[0][1] * $M[1][0];
    $y = $F[0][0] * $M[0][1] + 
         $F[0][1] * $M[1][1];
    $z = $F[1][0] * $M[0][0] + 
         $F[1][1] * $M[1][0];
    $w = $F[1][0] * $M[0][1] +
         $F[1][1] * $M[1][1];
  
    $F[0][0] = $x;
    $F[0][1] = $y;
    $F[1][0] = $z;
    $F[1][1] = $w;
}
  
// Function to calculate F[][]
// raise to the power n
function power(&$F, $n)
{
    // Base case
    if ($n == 0 || $n == 1)
        return;
  
    // take 2D array to store number's
    $M = array(array(1, 1), array(1, 0));
  
    // run loop till MSB > 0
    for ($m = getMSB($n); $m; $m = $m >> 1) 
    {
        multiply($F, $F);
  
        if ($n & $m) 
        {
            multiply($F, $M);
        }
    }
}
  
// To return fibonacci numebr
function fib($n)
{
    $F = array(array( 1, 1 ),
               array( 1, 0 ));
    if ($n == 0)
        return 0;
    power($F, $n - 1);
    return $F[0][0];
}
  
// Driver Code
  
// Given n
$n = 6;
  
echo fib($n) . " ";
  
// This code is contributed by ita_c
?>


输出:
8

时间复杂度: -O(logn)和空间复杂度: -O(1)。