斐波那契字符串,剪枝代码实现
题目出自:
https://developer.aliyun.com/article/743552?spm=a2c6h.12873639.0.0.564ed032feoyt8
题目概述:
Tom发现了一种神奇的字符串-斐波那契字符串,定义f[1]=0,f[2]=1,
对于所有的i>2都有f[i]=f[i-2]+f[i-1],其中“+”代表拼接,
比如01+10=0110,
现在对于字符串f[n],请判断f[n]的第k项是0,还是1?
输入两个数字n和k(n<=300,k<=1000000000)。
输出f[n]的第k位,如果k大于f[n]的位数,则输出-1。
思路:参见原文解法二,以下为具体代码实现,一些细节的思路也写在commet中。
class Solution {
public int solution(int n, int k) {
/*
先计算len数组,用len数组储存Fibonacci字符串长度。可以看出来,k的取值小于Fibonacci数列第45项,所以max_n取45
maxK = 1_000_000_000;
len[44] = 1_134_903_170;
max_n = 45;
*/
final int max_n = 45;
int[] len = new int[max_n];
len[0] = 1
len[1] = 1
for (int i = 2; i < max_n; i++) {
len[i] = len[i-2] + len[i-1];
}
if(n==1)
return 0;
if(n==2)
return 1;
//当输入的n > 47时,斐波那契字符串的长度超出了int型变量k的表示范围。根据k的int表示范围(小于等于2^31-1)这一特性,提前进行推断剪枝
if(n>max_n)
n=max_n;
//如果k大于f[n]的位数,则输出-1
if(k>len[n-1])
return -1;
// 开始剪枝
// 利用斐波那契数列的性质,自顶向下对问题逐步剪枝,定位需要判断的数字位置。
n=n-1; // n-->index
int len1;
while(k>1 && n>2){
len1 = len[n-2]; ////n的前半部分,n-2
if(k>len1){
//说明在n的后半部分
n = n-1;
k = k - len1;
}else{
//说明在n的前半部分
n = n-2; //n-2,进行下一波对比
}
}
n = n+1; // n-->length
String[] arr = new String[n];
arr[0] = "0";
arr[1] = "1";
for (int i = 2; i < n; i++) {
arr[i] = arr[i-2] + arr[i-1];
}
return arr[n - 1].charAt(k - 1) - '0';
}
}
浙公网安备 33010602011771号