获取第 n 个斐波那契数的简单代码

Simple code to obtain n-th number of Fibonnaci

本文关键字:简单 代码 获取      更新时间:2023-10-16

我只是想生成一段有效的代码来获取斐波那契数列的第n个数字,并使用下面的代码来执行此操作。但是,我Expression: vector subscript out of range收到错误,不知道为什么会发生。

int Fib(int n)
{
    vector<int> output;
    output.reserve(n);
    output[0] = 1; output[1] = 2;
    for(int i = 2; i <=n; ++i)
    {
        output.push_back(output[i-1]+ output[i-2]);
    }
return output[n];
}

原始代码返回 Fib(0( 的无效值(1 而不是 0(https://en.wikipedia.org/wiki/Fibonacci_number。

以下代码修复了此问题和矢量初始化:

int fib(int n)
{
    vector<int> output;
    output.resize(n+1);
    output.clear();
    output.push_back(0);
    output.push_back(1);
    for (int i=2; i <= n; i++)
    {
        output.push_back(output[i-1] + output[i-2]);
    }
    return output[n];
}

无论如何,甚至有一个更好的实现,不需要使用向量:

int fib(int n) 
{
    if ( n == 0 || n == 1 ) 
        return n;
    int fib1 = 0; 
    int fib2 = 1;
    int fib = 0;
    for ( int i = 2; i < n; i++ ) 
    {
        fib = fib1 + fib2;
        fib1 = fib2;
        fib2 = fib;
    }
    return fib;
}

std::vector::reserve只是容器为数据预分配存储的性能提示;它实际上并没有用n元素填充向量。因此,当您尝试访问元素(如 output[0] = 1 (时,您正在访问不存在的元素。

您可以简单地切换到 std::vector::resize ,它可以执行您想要的操作。请注意,在 thas std::vector::push_back 使算法出错后,您应该这样做

output[n] = output[n-1] + output[n-2];

顺便说一下,这种方法不是很有效,至少由于不必要的内存分配。像这样的东西应该更快:

int Fib(int n)
{
    int a = 0, b = 1;
    for(int i = 0; i < n; ++i)
    {
        int t = a + b;
        a = b;
        b = t;
    }
    return a;
}

保留 != 调整大小

您不是在插入以后可以使用下标operator[]访问的默认构造元素,而是暗示分配未初始化的内存,这只会影响容量,而不会影响容器的大小因此,以这种方式访问元素是无效的。

即使这些预循环线也是无效的

output.reserve(n);
output[0] = 1; output[1] = 2;

您应该宁愿使用 resize() 并注意push_back随后会增加向量的维度(因此,要么在代码中一直使用 push_back s,要么执行resize()并使用下标访问(。

int Fib(int n)
{ // Lacks error checking if n < 2
  vector<int> output;
  output.resize(n);
  output[0] = 1; output[1] = 2;
  for (int i = 2; i < n; ++i)
  {
    output[i] = output[i - 1] + output[i - 2];
  }
  return output[n-1];
}

额外提示

  • 如果你只对n-th斐波那契数感兴趣,你不需要带有向量的完整历史,你可以缓存序列中的最后两个数字

  • 对于大n这种方法可能行不通,在对数时间内运行的更聪明的方法(尽管您仍然需要做一些简单的矩阵乘法(可能是以下 [线性递归关系]

此行

output.reserve(n);

不会向量添加元素 - 它只是在内存中为该数量的项目保留空间。它不会用任何东西填充向量 - 您可以通过在返回零的向量上调用 size() 来验证这一点。因此在这里

output[0] = 1; output[1] = 2;

您正在尝试修改特定索引处的值 - 但这些索引上没有任何内容,并且您的索引超出了向量数组边界(如消息所示(。在尝试读取或写入特定索引之前,实际上应该填充向量。

在您的情况下,只需添加

output.push_back(1);
output.push_back(2);

之前您的循环将解决此问题(或者按照其他答案的建议使用 resize(。

int fib()
{
cout<<"Enter the term";
cin>>n;
int f=0,f1=1,f2=0;
for(i=1;i!=n;i++)
{
f=f1+f2;
f1=f2;
f2=f;
}
if(i==n)
cout<<n<<"'th term is"<<f;
}
是否

足够简单,如果我错了,请纠正我

>std::vector::reserve只增加向量的容量(即分配的空间(,它实际上并没有增加向量的大小(即项目数(。

所以:

output[0] = 1; output[1] = 2;

是不合法的,因为您尝试访问大小为 0 的向量中的前两项。

相反,请执行:

output.push_back(1);
output.push_back(2); // this should probably push back 1 though, if you want the Fibonacci sequence

此外,您尝试向向中添加一个太多的项目,因此将循环更改为:

for(int i = 2; i < n; ++i)

(即使用<而不是<=(。

您还必须相应地修改 return 语句:

return output[n - 1];

你应该做这样的事情:

std::vector<int> output;
        output.resize(n+1); // resize not reserv  & n+1 because the <=n
        output[0] = 1; output[1] = 2;
        for (int i = 2; i <= n; ++i)
        {
            output[i]=(output[i - 1] + output[i - 2]); // indexing not push_back
        }

顺便说一句,如果你真的想使用似乎不是最佳选择的向量,你最好做一些事情:

std::vector<unsigned long long> output;
output.resize(n+1);
output[0] = 1; output[1] = 2;
const auto end_of_output(std::end(output));
for (auto& it = std::begin(output) + 2; it < end_of_output; ++it){
    *it = *(it - 1) + *(it - 2);
}

由于您为n变量保留了一个空间,因此向量最多可以索引 n-1 ,而返回 output[n] ,从而导致错误:vector subscript out of range 。要为最后一个变量留出空间,您应该使用 reserve(n+1) .但是,请注意,这将是n+1斐波那契数。

此外,vector.reserve() 将内存分配给向量而不对其进行初始化。因此,您无法访问诸如 output[0] .相反,您应该push_back索引 0 和 1 处的值(以及其他值(,或者使用 vector.resize()然后按索引访问所有元素,而不是使用 push_back

有关 resizereserve 之间区别的说明,请参阅此 SO 线程。