【回溯】【leetcode】将数字字符串拆分成斐波那契序列

题目:

给定一个数字字符串 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]

来源:

842. 将数组拆分成斐波那契序列

解题思路:回溯

定义一个变量n,记录字符串[start, i]的数值。第一次递归(start=0)中for循环情况如下:

  • 递归终止条件:数字字符串处理完成
  • 结果满足条件:数字字符串处理完成,并且结果至少3个数
  • 剪枝条件:找到一个后,或数字超int最大值,或不满足斐波那契公式(也可以增加判断:当前2个数字之和小于当前数字n时,退出for循环,因为后面的数字n更大)
class Solution {
public:
    vector<int> result;
    vector<int> path;
    bool finish;
    vector<int> splitIntoFibonacci(string S) {
        finish = false;
        // 处理开头的0
        int start = 0;
        while (start < S.size() && S[start] == '0') {
            path.push_back(0);
            start++;
        }
        back(S, start);
        return result;
    }
    void back(const string& s, int start) {
        if (path.size() > 2 && start == s.size()) {
            finish = true;
            result = path;
            return;
        }

        long n = 0;
        for (int i = start; i < s.size(); i++) {
            if (finish) break;
            n = n * 10 + s[i] - '0'; // n:[start,i]内的数字
            if (n > 0x7fffffff) break;
            int sz = path.size();
            if (sz < 2 || (long)path[sz-1] + (long)path[sz-2] == n) {
                path.push_back(n);
                back(s, i + 1);
                path.pop_back();
            }
        }
    }
};

每个块的数字一定不要以零开头,这种情况没有处理,居然也能通过。例如:11203应当返回[],而本代码却返回了[1,1,2,3]。

补救的方法是在int sz = path.size();后面增加一行:if (sz > 1 && s[start] == '0') break;表示,当序列至少2个数的前提下,start所指向的数字不能是0,若是0则跳过。

猜你喜欢

转载自blog.csdn.net/hbuxiaoshe/article/details/114986607
今日推荐