842. Split Array into Fibonacci Sequence
Given a string S of digits, such as S = "123456579", we can split it into a Fibonacci-like sequence [123, 456, 579].
Formally, a Fibonacci-like sequence is a list F of non-negative integers such that:
0 <= F[i] <= 2^31 - 1, (that is, each integer fits a 32-bit signed integer type);
F.length >= 3;
and F[i] + F[i+1] = F[i+2] for all 0 <= i < F.length - 2.
Also, note that when splitting the string into pieces, each piece must not have extra leading zeroes, except if the piece is the number 0 itself.
Return any Fibonacci-like sequence split from S, or return [] if it cannot be done.
Example 1:
Input: "123456579"
Output: [123,456,579]
Example 2:
Input: "11235813"
Output: [1,1,2,3,5,8,13]
Example 3:
Input: "112358130"
Output: []
Explanation: The task is impossible.
Example 4:
Input: "0123"
Output: []
Explanation: Leading zeroes are not allowed, so "01", "2", "3" is not valid.
Example 5:
Input: "1101111"
Output: [110, 1, 111]
Explanation: The output [11, 0, 11, 11] would also be accepted.
Note:
- 1 <= S.length <= 200
- S contains only digits.
解析:
找出一个字符串中的斐波拉契数列,如果没有就返回一个空数组,需要注意的是01这样的数字是不被允许的。这个题的关键就是定位斐波拉契数列的第一项和第二项,这样整个数列就定下来了,所以遍历所有可能的第一项和第二项找到可行的解就可以返回了。
参考答案
自己写的(很菜):
class Solution {
public List<Integer> splitIntoFibonacci(String S) {
List<Integer> res = new ArrayList<>();
int first;
int second;
for (int i = 0; i < S.length()-2; i++) {
try {
first = Integer.valueOf(S.substring(0, i+1));
} catch (NumberFormatException e) {
break;
}
for (int j = i+1; j < S.length(); j++) {
try {
second = Integer.valueOf(S.substring(i+1, j+1));
} catch (NumberFormatException e) {
break;
}
int f1 = first;
int f2 = second;
int f3 = first + second;
int startIndex = j+1;
res.add(f1);
res.add(f2);
try {
while (startIndex + Integer.toString(f3).length() <= S.length() && f3 == Integer.valueOf(S.substring(startIndex, startIndex+Integer.toString(f3).length()))) {
startIndex += Integer.toString(f3).length();
res.add(f3);
int t = f2;
f2 = f1 + f2;
f3 = t + f3;
f1 = t;
}
} catch (NumberFormatException e) {
}
if (startIndex == S.length() && res.size() >= 3) {
return res;
} else {
res.clear();
}
if (second == 0) {
break;
}
}
if (first == 0) {
break;
}
}
return res;
}
}
运行时间10ms,主要是在搜索是否是可行解的时候直接遍历,时间消耗比较多。另外代码写的也不够简洁,有很多可以优化的点。
别人的答案:
class Solution {
public List<Integer> splitIntoFibonacci(String S) {
int firstBound = S.charAt(0) == '0' ? 1 : S.length() - 2;
for(int i = 0;i < firstBound;i++) {
int secondBound = S.charAt(i+1) == '0' ? i + 2 : S.length() - 1;
try {
int first = Integer.parseInt(S.substring(0, i+1));
for(int j = i+1;j < secondBound;j++) {
try{
int second = Integer.parseInt(S.substring(i+1, j+1));
int sum = first + second;
List<Integer> ans = new ArrayList<>(Arrays.asList(first, second));
if(dfs(ans, S.substring(j+1), sum)) return ans;
} catch (NumberFormatException e) {
break;
}
}
} catch (NumberFormatException e) {
break;
}
}
return new ArrayList<>();
}
private boolean dfs(List<Integer> ans, String s, int sum) {
if(s.length() == 0) return true;
String cur = Integer.toString(sum);
if(!s.startsWith(cur)) return false;
int nextSum = ans.get(ans.size()-1) + sum;
ans.add(sum);
return dfs(ans, s.substring(cur.length()), nextSum);
}
}
他们的代码写的简洁很多,用了dfs搜素速度更快,8ms就跑完用例,用s.startWith()比我把String转换成int在比较效率更高,而且不用考虑越界和NumberFormatException。