[leetcode][842] Split Array into Fibonacci Sequence

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. 1 <= S.length <= 200
  2. 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。

猜你喜欢

转载自www.cnblogs.com/ekoeko/p/9594428.html