1. 程式人生 > 實用技巧 >【刷題-LeetCode】306. Additive Number

【刷題-LeetCode】306. Additive Number

  1. Additive Number

Additive number is a string whose digits can form additive sequence.

A valid additive sequence should contain at least three numbers. Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two.

Given a string containing only digits '0'-'9'

, write a function to determine if it's an additive number.

Note: Numbers in the additive sequence cannot have leading zeros, so sequence 1, 2, 03 or 1, 02, 3 is invalid.

Example 1:

Input: "112358"
Output: true
Explanation: The digits can form an additive sequence: 1, 1, 2, 3, 5, 8. 
             1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8

Example 2:

Input: "199100199"
Output: true
Explanation: The additive sequence is: 1, 99, 100, 199. 
             1 + 99 = 100, 99 + 100 = 199

Constraints:

  • num consists only of digits '0'-'9'.
  • 1 <= num.length <= 35

Follow up:
How would you handle overflow for very large input integers?

  • 回溯法。注意回溯中,在進入分支之後,還要退出分支
  • 大數運算。用字串實現大數的加減乘除
// 大數,只需要過載加法
class BigNum{
public:
    string val;
    BigNum(string s, bool hasreversed = false){
        if(!hasreversed){
            reverse(s.begin(), s.end());
        }
        val = s;
    }
    void Print(){
        for(int i = val.size()-1; i>=0; --i)cout << val[i];
        cout << endl;
    }
    //先加兩個字串公有的部分,再加上剩下的部分
    //如果進位不為0,還要加上進位
    BigNum operator + (BigNum &b){
        string s1 = b.val, res;
        int carry = 0, i = 0;
        while(i < s1.size() && i < val.size()){
            int tmp = carry + (s1[i]-'0') + (val[i]-'0');
            carry = tmp / 10;
            res += tmp % 10 + '0';
            i++;
        }
        while(i < s1.size()){
            int tmp = carry + (s1[i]-'0');
            carry = tmp / 10;
            res += tmp % 10 + '0';
            i++;
        }
        while(i < val.size()){
            int tmp = carry + (val[i]-'0');
            carry = tmp / 10;
            res += tmp % 10 + '0';
            i++;
        }
        if(carry)res += carry + '0';
        return BigNum(res, true);
    }
};

class Solution {
public:
    bool isAdditiveNumber(string num) {
        vector<BigNum>path;
        return dfs(num, 0, path);
    }
    bool dfs(string &num, int pos, vector<BigNum>&path){
        //結束條件,當pos到達了字串末尾,則列舉完畢,看path的長度,如果大於2,說明前面的列舉是成功的
        if(pos >= num.size())return path.size() >= 3;
        int len = path.size();
        // 如果len<2,說明最前面的兩個數字還沒有選出來,列舉選擇即可
        // 不能出現字首0,即02 00這些是不合法的,只能選成0
        if(len < 2){
            for(int i = 1; i <= num.size(); ++i){
                if(num[0] == '0' && i > 1)break;
                path.push_back(BigNum(num.substr(0, i)));
                for(int j = i+1; j <= num.size(); ++j){
                    if(num[i] == '0' && j > i + 1)break;
                    path.push_back(BigNum(num.substr(i, j-i)));
                    if(dfs(num, j, path)){
                        return true;
                    }else{
                        path.pop_back();
                    }
                }
                path.pop_back();
            }
        }else{
            // 算出前兩個數字的和,看對應的字串是不是num的子串,不是的話返回,是的話往後搜尋
            BigNum next_int = path[len-2] + path[len-1];
            string next_str = next_int.val;
            reverse(next_str.begin(), next_str.end());
            if(num.substr(pos, next_str.size()) == next_str){
                path.push_back(next_int);
                bool res = dfs(num, pos + next_str.size(), path);
                path.pop_back();
                return res;
            }else{
                return false;
            }
        }
        return false;
    }
};