斐波那契字符串,剪枝代码实现

题目出自:

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';
        }

}

  

posted @ 2020-09-08 11:59  littleFlyD  阅读(427)  评论(0)    收藏  举报