在牛客网上有这样一道题目:
思路疏通:
那么我们想要将一个数变成Fibonacci数列,首先必须先构造出一个Fibonacci数列,然后对比这个数和Fibnacci数的差值,题目问我们要求求出最小的步数,其实就是想要求出这个数和它前后相邻的两个Fibonacci数的差值大小,找出最小的数值,然后变成Fibnacci数。
废话少说,先贴上代码,进行每一步的剖析:
#include<stdio.h>
#include<math.h>
int main()
{
int a = 0 ; //定义第一个fibonacci数
int b = 1 ; //定义第二个fibonacci数
int n = 0; //定义需要比较的数
int min = 0; //定义最小步数
int c=0; //定义前两个fibonacci数的和(也就是每次求出的下一个fibonacci数)
scanf("%d",&n); //输入比较的数
while(1) //里面的1就是说明循环一直进行
//注:1为真,在while循环中,内部条件若为真,则一直运行
{
if(b==n) //因为比较的时候,n的值必须在a和b中间,这样才能求出差值,看是否最小步数
//所以当输入的n就是fibonacci数的时候,直接返回他的差值(0),说明他本身
//就是fibonacci数,不需要通过改变步数才能变成fibonacci数了
{
printf("%d",b-n); //返回0
break; //当找到了fibonacci数的时候,说明目标已经完成了,直接跳出循
//环,否则将一直循环。出不去程序内部,就会出现栈溢出现象
}
else //如果这个数没有一次就变成fibonacci数
{
if(b>n && n>a) //如果这个数在a和b中间,就可以进行差值计算
//注:此处的&&不是必要性存在,
//但是为了逻辑的严谨性,存在是代码严谨性的体现,可以直接将n包含在a和b的中间
{
//abs(n)是一个求数的绝对值的函数
if(abs(b-n)>abs(n-a)) //abs(b-n)>abs(n-a) ,说明这个数离b的步数小于离a的
//是这个数和相邻的数之间的步数绝对值
//因为步数应该是正数,所以应该用绝对值
{
min = abs(n-a); //将步数的最小值赋给min(最小步数)
printf("%d",min); //打印
break; //目标完成,必须自己跳出循环
}
else //或者另外一种情况,那就是这个数离b更近一些
{
min = abs(b-n); //将步数最小值赋给min
printf("%d",min); //打印
break; //跳出循环
}
}
else //如果n不在a和b中间的话,那就无操作,因为我们要求的必须是在两个
//fibonacci数之间才可以求出最小步数(min)
{
;
}
}
//因为上面的一系列操作只是对于fibonacci数列内部寻找最小步数的实现,但是却没有构造出来fibonacci数列,但是因为这是循环,而且只有将最初的数值先进行寻找操作才可以让后面的数值继续增加,否则就会错过第一次数值的遍历
a=b; //将第一组使用完了之后,就必须使用第二组,那就让b(后面的值)来覆盖a(前面的值)
b=c; //同样将后面的值覆盖前面的值
c=a+b; //fibonacci数列的本质,第三个数是前两个数的和
//注:在数值覆盖的时候必须是从左往右依次覆盖,因为如果使用第三个值去覆盖第二个值的话
// 当第二个值去覆盖第一个值的时候就会出现第一个值和第二个值相同的情况,那就是数据覆盖重复
// 这样就违背了fibonacci数列的本质
}
return 0;
}