题目描述
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数。
输入描述:
输入为一个正整数(1<=N<=1,000,000)
输出描述:
输出一个最小的步数变为Fibonacci数
示例:
输入:
15
输出:
2
解题思路
- 题目给的N范围太大,不能使用递归,否则复杂度会变很大。
- 一边生成Fibonacci数列的同时一边比较,找出那个比N大的值就可以停止。这样可以避免算出范围内的所有Fibonacci数浪费空间。
- 因为要找最小步数,而我们 不能确定
N左侧的Fibonacci数
距离N的步数最小还是N右侧的Fibonacci数
具体N的步数最小。
所以,保存N左右两边的Fibonacci数。
实现代码
class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n =sc.nextInt(); //1.取得N
//数列初始值,为了让1也参与比较,从0开始
int a = 0;
int b = 1;
int left = 0,right = 0; //2.保存n的左右两个数
while(true) {
int temp = a + b;
a = b;
b = temp; //要被比较数
if(b < n) {
left = b; //2.1一直在更新n左边的数
} else {
right = b; //2.2如果一旦出现大于n的数,就一定是n右侧的数,直接跳出循环
break;
}
}
//3.比较left和right哪个距离n走的步数小,选择小的步数输出。
System.out.println((n - left) < (right - n) ? (n - left):(right - n));
}
}