[Backtracking] [leetcode] Split the number string into Fibonacci sequence

topic:

Given a number string S, such as S = "123456579", we can divide it into Fibonacci-like sequences [123, 456, 579].

Formally, the Fibonacci sequence is a list F of non-negative integers and satisfies:

  • 0 <= F[i] <= 2^31-1, (that is, each integer conforms to the 32-bit signed integer type);
  • F.length >= 3;
  • For all 0 <= i <F.length-2, F[i] + F[i+1] = F[i+2] holds.

In addition, please note that when splitting the string into small blocks, the number of each block must not start with a zero, unless the block is the number 0 itself.

Return any set of Fibonacci-like sequence blocks split from S, or [] if it cannot be split.

Example 1:

Input: "123456579"
Output: [123,456,579]

source:

842. Split the array into Fibonacci sequences

Problem-solving ideas: backtracking

Define a variable n to record the value of the string [start, i]. The for loop in the first recursion (start=0) is as follows:

  • Recursive termination condition: digital string processing completed
  • The result satisfies the condition: the digital string processing is completed, and the result is at least 3 numbers
  • Pruning condition: After finding one, or the number exceeds the maximum value of int, or the Fibonacci formula is not satisfied (you can also add judgment: when the sum of the current two numbers is less than the current number n, exit the for loop, because the following number n Bigger)
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();
            }
        }
    }
};

The number of each block must not start with a zero. If this situation is not handled, it can actually pass. For example: 11203 should return [], but this code returns [1,1,2,3].

The remedy is to add a line after int sz = path.size();: if (sz> 1 && s[start] == ​​'0') break; means that when the sequence is at least 2 numbers, start is The number pointed to cannot be 0, if it is 0, skip it.

Guess you like

Origin blog.csdn.net/hbuxiaoshe/article/details/114986607