【Lintcode】1427. Split Array into Fibonacci Sequence

题目地址:

https://www.lintcode.com/problem/split-array-into-fibonacci-sequence/description

给定一个由数字构成的长 n n n的字符串 s s s,要求将其截取成若干部分,使得这些部分看成数字时就成为了斐波那契数列。返回这个数列。要求数列长度不小于 3 3 3,并且每个截取的部分除非自己是 0 0 0,否则不能含开头 0 0 0。并且,每个数小于等于 2 31 − 1 2^{31}-1 2311

容易看出,只需要前两个数定下来了,整个数列也就定下来了,所以我们只需要枚举前两个数是多少,然后向后推即可。推的同时注意开头零的问题。由于可能会截取出超过 2 31 − 1 2^{31}-1 2311的数,我们用long来做。代码如下:

import java.util.ArrayList;
import java.util.List;

public class Solution {
    /**
     * @param S: a string S of digits
     * @return: Return any Fibonacci-like sequence split from S
     */
    public List<Integer> splitIntoFibonacci(String S) {
        // write your code here
        List<Integer> res = new ArrayList<>();
        // i和j枚举的是前两个数的最后一位的位置
        for (int i = 0; i + 1 < S.length(); i++) {
            for (int j = i + 1; j < S.length(); j++) {
            	// start1是当前枚举的两个数的第一个数的开头位置,end1是其结尾位置,end2是枚举的两个数第二个数的结尾位置
                int start1 = 0, end1 = i, end2 = j;
                while (true) {
                	// 如果有开头0则直接退出循环,进行下一次枚举
                    if (end1 - start1 + 1 >= 2 && S.charAt(start1) == '0') {
                        break;
                    }
                    if (end2 - end1 >= 2 && S.charAt(end1 + 1) == '0') {
                        break;
                    }
                    
                    // 解析出两个数
                    long a = Long.parseLong(S.substring(start1, end1 + 1)), b = Long.parseLong(S.substring(end1 + 1, end2 + 1));
                    // 如果大于了最大int,则也退出循环,进行下一次枚举
                    if (a > Integer.MAX_VALUE || b > Integer.MAX_VALUE) {
                        break;
                    }
                    
                    // 算出第三个数c
                    long c = a + b;
                    String str = String.valueOf(c);
                    // 如果后面截不出c,退出循环,进行下一次枚举
                    if (S.indexOf(str, end2 + 1) != end2 + 1) {
                        break;
                    }
                    
                    // 我们计划每次while循环都加入第二个数,只有进行第一次while的时候,我们需要把第一个数加进去
                    if (start1 == 0) {
                        res.add((int) a);
                    }
                    res.add((int) b);
                    
                    // 把指针都重新调整
                    start1 = end1 + 1;
                    end1 = end2;
                    end2 += str.length();
                    
                    // 如果第二个数已经到了最后一个字符,并且列表里的数已经不少于2个了,
                    // 那加上最后一个恰好不少于3个,就说明找到了,返回之
                    if (end2 == S.length() - 1 && res.size() >= 2) {
                        res.add((int) c);
                        return res;
                    }
                }
                
                // 退出了while循环,说明没找到答案,则清空列表
                res.clear();
            }
        }
        
        return res;
    }
}

时间复杂度 O ( n 2 ) O(n^2) O(n2),空间 O ( n ) O(n) O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值