【LeetCode】每日一題842. 將陣列拆分成斐波那契序列
阿新 • • 發佈:2020-12-10
842. 將陣列拆分成斐波那契序列
給定一個數字字串 S,比如 S = “123456579”,我們可以將它分成斐波那契式的序列 [123, 456, 579]。
形式上,斐波那契式序列是一個非負整數列表 F,且滿足:
- 0 <= F[i] <= 2^31 - 1,(也就是說,每個整數都符合 32 位有符號整數型別);
- F.length >= 3;
- 對於所有的0 <= i < F.length - 2,都有 F[i] + F[i+1] = F[i+2] 成立。
另外,請注意,將字串拆分成小塊時,每個塊的數字一定不要以零開頭,除非這個塊是數字 0 本身。
返回從 S 拆分出來的任意一組斐波那契式的序列塊,如果不能拆分則返回 []。
示例 1:
輸入:"123456579"
輸出:[123,456,579]
示例 2:
輸入: "11235813"
輸出: [1,1,2,3,5,8,13]
示例 3:
輸入: "112358130"
輸出: []
解釋: 這項任務無法完成。
示例 4:
輸入:"0123"
輸出:[]
解釋:每個塊的數字不能以零開頭,因此 "01","2","3" 不是有效答案。
示例 5:
輸入: "1101111"
輸出: [110, 1, 111]
解釋: 輸出 [11,0,11,11] 也同樣被接受。
提示:
- 1 <= S.length <= 200
- 字串 S 中只含有數字。
解題思路:
沒做出來~,參考的官方解答。
本質上還是暴力解法,只是暴力的更優美~。使用「回溯」+「剪枝」大大提升了效率。解釋在程式碼註釋中。
方法一:回溯 + 剪枝
public List<Integer> splitIntoFibonacci(String S) {
List<Integer> list = new ArrayList<> ();
backtrack(list, S, 0);
return list;
}
public boolean backtrack(List<Integer> list, String S, int index) {
// 遞迴終止條件,遍歷到末尾時,陣列長度必須大於等於3
if (index == S.length()) {
return list.size() >= 3;
}
for (int i = index; i < S.length(); i++) {
// 排除首位是 0
if (i > index && S.charAt(index) == '0') {
break;
}
// 用long 接收,避免超過int 最大值
long longValue = Long.parseLong(S.substring(index, i + 1));
if (longValue > Integer.MAX_VALUE) {
break;
}
int intValue = (int) longValue;
// 陣列有兩個以上的元素時,當前值必須等於末尾兩個元素的和
if (list.size() >= 2) {
int sum = list.get(list.size() - 1) + list.get(list.size() - 2);
if (intValue < sum) {
continue;
} else if (intValue > sum) {
break;
}
}
list.add(intValue);
// 繼續向下遞迴,失敗說明當前元素不存在解,刪除當前元素
if (!backtrack(list, S, i + 1)) {
list.remove(list.size() - 1);
} else {
return true;
}
}
return false;
}