1. 程式人生 > 其它 >【Lintcode】1427. Split Array into Fibonacci Sequence

【Lintcode】1427. Split Array into Fibonacci Sequence

技術標籤:# 棧、佇列、串及其他資料結構列表java演算法字串

題目地址:

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)