题目地址:
https://leetcode.com/problems/split-array-into-fibonacci-sequence/
给定一个只含数字的字符串 s s s,判断其是否能拆成“斐波那契序列”,这里的含义是,是否存在一种拆分,使得 s = s 1 + s 2 + . . . + s k s=s_1+s_2+...+s_k s=s1+s2+...+sk,并且如果将 s i s_i si都看成数字的话,有 ∀ 3 ≤ i ≤ k , s i = s i − 1 + s i − 2 \forall 3\le i\le k, s_i=s_{i-1}+s_{i-2} ∀3≤i≤k,si=si−1+si−2。如果存在,则返回一个正整数列表,使得上面的等式成立;否则返回空列表。不需要考虑 s i s_i si大于 2 32 − 1 2^{32}-1 232−1的情况。
方法就是暴力枚举。容易看出只需枚举前两个数是谁即可,枚举完了之后向后不断挪动指针,截出两个数的和并判断。可以额外写一下高精度加法,并且由于不能考虑大于 2 32 − 1 2^{32}-1 232−1的情况,所以还要写一个函数专门判断这一点。代码如下:
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<Integer> splitIntoFibonacci(String s) {
List<Integer> res = new ArrayList<>();
for (int i = 1; i < s.length(); i++) {
for (int len = 1; i + len - 1 < s.length(); len++) {
// a是第一个数的起始坐标,b是第二个数的起始坐标,c是第二个数的最后一位向后一步的位置
int a = 0, b = i, c = b + len;
String n = s.substring(a, b);
// 如果两个数有一个不合法,那就直接break了,之后再枚举只能枚举出更不合法的情况
if (!check(n) || !check(s.substring(b, c))) {
break;
}
res.add((Integer.parseInt(n)));
while (true) {
// 如果有前导0则直接退出
if (s.charAt(a) == '0' && b - a != 1) {
break;
}
if (s.charAt(b) == '0' && c - b != 1) {
break;
}
// 截出两个数字
String n1 = s.substring(a, b), n2 = s.substring(b, c);
// 如果不合法则直接break
if (!check(n1) || (!check(n2) && c != s.length())) {
break;
}
// 把第二个数加入res,并将a和b向后挪
res.add(Integer.parseInt(n2));
a = b;
b = c;
// 求一下和,用高精度加法来求
String next = add(n1, n2);
// 更新一下c的位置
c = c + next.length();
// 如果第二个数恰好就是结尾了,判断一下res是否存了超过两个数,
// 如果是,说明找到答案了,返回之;否则break
if (b == s.length()) {
if (res.size() > 2) {
return res;
} else {
break;
}
}
// 如果长度不够也直接break
if (b + next.length() > s.length()) {
break;
}
// 如果求出来的和不符合,也break
if (!next.equals(s.substring(b, b + next.length()))) {
break;
}
}
// break了说明res里存的是不合法的情形,清空列表
res.clear();
}
}
return res;
}
private String add(String n1, String n2) {
StringBuilder sb = new StringBuilder();
int n = 0;
for (int i = n1.length() - 1, j = n2.length() - 1; i >= 0 || j >= 0; ) {
int x = 0, y = 0;
if (i >= 0) {
x = n1.charAt(i) - '0';
i--;
}
if (j >= 0) {
y = n2.charAt(j) - '0';
j--;
}
n += x + y;
sb.append(n % 10);
n /= 10;
}
if (n == 1) {
sb.append(1);
}
return sb.reverse().toString();
}
// 判断n是否大于了32位最大整数
private boolean check(String n) {
String max = "2147483647";
if (n.length() != max.length()) {
return n.length() < max.length();
}
for (int i = 0; i < n.length(); i++) {
if (n.charAt(i) > max.charAt(i)) {
return false;
}
}
return true;
}
}
时间复杂度 O ( n 3 ) O(n^3) O(n3),空间 O ( n ) O(n) O(n)。