题目如下:
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
解题思路:这道题就是找到输入的数n离得最近的Fibonacci数f,求这个Fibonacci数f与输入数n之间的差值绝对值的大小|n-f|,输出即是需要的答案。关键就是如何得到这个Fibonacci数f。如果把0-n的所有Fibonacci数得到再存储,需要的空间有点大。那么如何解决?
这个思路不对,另外换个方向。
假设输入的数n和离得最近的Fibonacci数f的差值为temp0,输入的数n和f的下一个Fibonacci值f1为temp1,则temp0和temp1的乘积肯定为负值(如果其中一个差值为0,则输出0即可)。即从0开始递归求Fibonacci值,则当temp0和temp1的乘积变为负值时,判断temp0和temp1的大小,输出较小者的绝对值即可。
感觉这个解法不是最优,因为从最小值递归,计算量还是挺大的。或许求Fibonacci值这里可以优化下。但是能出结果就好啦。暂时只能想到这个思路。慢慢来。
代码如下:
import java.util.*;
public class getFibonacci
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
while (in.hasNext())
{
int N = in.nextInt();
int k=0;
boolean flag=false;
//数据类型用int会导致一些用例通不过,主要是因为有乘积导致溢出不能正确显示
long tres=0;
while (flag==false)
{
long temp0=N-getFnum(k);
long temp1=N-getFnum(k+1);
long temp=temp0*temp1;
if (temp==0)
{
flag=true;
tres=0;
}else if(temp<0){
flag=true;
tres=Math.min(Math.abs(temp0), Math.abs(temp1));
}else {
k=k+1;
}
}
System.out.println(tres);
}
}
private static long getFnum(int n)
{
long result;
if (n==0)
{
result=0;
}else if(n==1){
result=1;
}else {
result=getFnum(n-1)+getFnum(n-2);
}
return result;
}
}
另外这里还有一个数据类型的问题需要注意,temp为temp0和temp1的乘积,所以将他们都设为long型,防止数据较大时造成测试用例通不过。