题目描述:
Fibonacci数列是这样定义的:
F[0] = 0
F[1] = 1
for each i ≥ 2: F[i] = F[i-1] + F[i-2]
因此,Fibonacci数列就形如:0, 1, 1, 2, 3, 5, 8, 13, …,在Fibonacci数列中的数我们称为Fibonacci数。给你一个N,你想让其变为一个Fibonacci数,每一步你可以把当前数字X变为X-1或者X+1,现在给你一个数N求最少需要多少步可以变为Fibonacci数。
输入描述:
输入为一个正整数N(1 ≤ N ≤ 1,000,000)
输出描述:
输出一个最小的步数变为Fibonacci数”
例如:
输入:15
输出:2
解题思路:
先来说一下我的解题思路吧:
(1)首先我想到的是输入的正整数不能超过1,000,000 < F[32],所以我首先定义了一个数组fib_array[33],用来存放从第0个到第32个Fibonacci数。
(2)写一个函数用来求解Fibonacci数列,这里我用的循环加迭代的方法求解的,因为我觉得用递归求解可能时间复杂度会太大。
(3)我定义了一个链表 listmod_arr,用来存放我们输入的数N与数组fib_array[33]中每个元素的差值,需要注意的是,如果差值为负数,需要取其绝对值(题目因为要求输出一个正数)。至于我为什么用链表而不用其他容器,是因为list中有一个借口sort(),可以直接用来排序 这给我们减少了代码量。
(4)给链表中这些差值排完序之后,输出链表的首元素就是题目所要求的的 “最小步数”了。
我的想法真的特别简单和粗暴(/捂脸),看到这里,就可以开始写代码了:
代码实现:
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<list>
using namespace std;
//求Fibonacci数列
int fib(int n)
{
int f0 = 0;
int f1 = 1;
int fn = 0;
for (int i = 2; i < n; i++)
{
fn = f0 + f1;
f0 = f1;
f1 = fn;
}
return fn;
}
int main()
{
int ret;
int array_fib[33]; //存Fibonacci数列
for (int i = 0; i < 33; i++)
{
array_fib[i] = fib(i);
}
int N;
list<int>mod_arr;
cin >> N; //输入N
for (int i = 0; i < 33; i++)
{
if (N == array_fib[i])//输入的数在Fibonacci数列中,步数为0
{
cout << 0;
return 0;
}
else //不在的话,求其差值存入链表
{
if (array_fib[i] - N>0)
mod_arr.push_back(array_fib[i] - N);
else
mod_arr.push_back(-(array_fib[i] - N));
}
}
mod_arr.sort(); //给链表里的数据排序
list<int>::iterator it = mod_arr.begin(); //取出最小步数
cout << *it << endl;
return 0;
system("pause");
}