491, the backtracking algorithm solution splits the array into Fibonacci sequences

Insert picture description here

If you want to see more algorithm questions, you can scan the QR code above to follow my WeChat official account " Data Structure and Algorithms ". Up to now, I have updated more than 500 algorithm questions in the official account , some of which have been sorted into pdf documents. , As of now, there are more than 800 pages in total (and will continue to increase), you can reply to the keyword "pdf" in the official account to download.


Problem Description

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 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]

Example 2:

Input : "11235813"

Output : [1,1,2,3,5,8,13]

Example 3:

Input : "112358130"

Output : []

Explanation : This task cannot be completed.

Example 4:

Input : "0123"

Output : []

Explanation : The number of each block cannot start with zero, so "01", "2", and "3" are not valid answers.

Example 5:

Input : "1101111"

Output : [110, 1, 111]

Explanation : The output [11,0,11,11] is also accepted.


prompt:

  • 1<=S.length<= 200
  • The string S contains only numbers.

Backtracking algorithm solution

This question is to split the string S into some substrings, and these substrings satisfy the relationship of the Fibonacci sequence. For this problem, we can use the backtracking algorithm to solve it. The backtracking algorithm is actually a process of continuous attempts . Once the attempt is successful, it will be successful. If the attempt fails, it will return to the previous step. Note that when you return to the previous step, you will Restore the state to the state of the previous step. Backtracking algorithm will not be introduced too much here. For the problem-solving ideas of backtracking algorithm, you can see 450. What is a backtracking algorithm? You can read it at first glance, and it will be invalid once you write it .


The backtracking algorithm actually has a classic template

private void backtrack("原始参数") {
    
    
    //终止条件(递归必须要有终止条件)
    if ("终止条件") {
    
    
        //一些逻辑操作(可有可无,视情况而定)
        return;
    }

    for (int i = "for循环开始的参数"; i < "for循环结束的参数"; i++) {
    
    
        //一些逻辑操作(可有可无,视情况而定)

        //做出选择

        //递归
        backtrack("新的参数");
        //一些逻辑操作(可有可无,视情况而定)

        //撤销选择
    }
}

The same is true for this question. Let’s first continuously intercept the string to see if it can form a Fibonacci sequence. If it can’t, go back to the previous step. If it can, continue to go down. For details, let’s look at the figure below. , Here is a picture drawn with reference to example 1, but the number is shortened, only 124557, because if there are more numbers, the picture is too big to draw.

Insert picture description here

Understand the above principles, the code is much simpler, let's look at the code

public List<Integer> splitIntoFibonacci(String S) {
    
    
    List<Integer> res = new ArrayList<>();
    backtrack(S.toCharArray(), res, 0);
    return res;
}

public boolean backtrack(char[] digit, List<Integer> res, int index) {
    
    
    //边界条件判断,如果截取完了,并且res长度大于等于3,表示找到了一个组合。
    if (index == digit.length && res.size() >= 3) {
    
    
        return true;
    }
    for (int i = index; i < digit.length; i++) {
    
    
        //两位以上的数字不能以0开头
        if (digit[index] == '0' && i > index) {
    
    
            break;
        }
        //截取字符串转化为数字
        long num = subDigit(digit, index, i + 1);
        //如果截取的数字大于int的最大值,则终止截取
        if (num > Integer.MAX_VALUE) {
    
    
            break;
        }
        int size = res.size();
        //如果截取的数字大于res中前两个数字的和,说明这次截取的太大,直接终止,因为后面越截取越大
        if (size >= 2 && num > res.get(size - 1) + res.get(size - 2)) {
    
    
            break;
        }
        if (size <= 1 || num == res.get(size - 1) + res.get(size - 2)) {
    
    
            //把数字num添加到集合res中
            res.add((int) num);
            //如果找到了就直接返回
            if (backtrack(digit, res, i + 1))
                return true;
            //如果没找到,就会走回溯这一步,然后把上一步添加到集合res中的数字给移除掉
            res.remove(res.size() - 1);
        }
    }
    return false;
}

//相当于截取字符串S中的子串然后转换为十进制数字
private long subDigit(char[] digit, int start, int end) {
    
    
    long res = 0;
    for (int i = start; i < end; i++) {
    
    
        res = res * 10 + digit[i] - '0';
    }
    return res;
}

to sum up

There are not many algorithmic question types that really have templates, but the backtracking algorithm is one of them. It is just that different types of questions need to be modified differently. As long as you master this template, you can slightly modify many backtracking algorithm question types. It's easy to make.

Guess you like

Origin blog.csdn.net/abcdef314159/article/details/112498301