1. 程式人生 > 實用技巧 >306. Additive Number

306. Additive Number

問題:

給定一個由0~9組成的字串,判斷該字串是否為一個可加字串。

可加字串:對字串進行切分後,各切片構成的數字,除了前兩個數字外,之後的數字都等於前兩個之和。

⚠️ 注意:每個切片數字若不等於0,則不能以'0'開頭。

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

  

解法:Backtracking(回溯演算法)

path:到當前位置為止,切分出來的結果

optlists:num的第pos位開始,可切出來的任意長度子串。

另,由於第一個和第二個數字和其他不同,因此要對第一個和第二個數字進行遍歷嘗試。

⚠️ 注意:這裡第一個第二個數字的嘗試結束,也要記得從path中刪除嘗試過的結果。path.pop_back()。

  • 第一個:num[0~i]:size:i屬於1~num.size/2 (餘留“和”的長度)
  • 第二個:num[i~i+j]:size:j屬於1~(num.size-i)/2(餘留“和”的長度)

⚠️ 注意:這裡num的長度最長可有35位,因此不能簡單使用字串->int,然後進行加法計算,可能出現int型別溢位。

因此,這裡實現string+string=string的add方法。

 1     string add(string a, string b) {
 2         string sum;
 3         int i = a.size()-1, j = b.size()-1, flag = 0;
 4         while(i>=0 || j>=0) {
 5             int s = flag + (i>=0?a[i]-'0':0) + (j>=0?b[j]-'0':0);
 6             sum.insert(sum.begin(), s%10
+'0'); 7 flag = s/10; 8 i--,j--; 9 } 10 if(flag) sum.insert(sum.begin(), flag+'0'); 11 return sum; 12 }

程式碼參考:

 1 class Solution {
 2 public:
 3     bool backtrack(string num, int pos, vector<string> path) {
 4         if(pos==num.size()) return true;
 5         string cur1 = path[path.size()-2];
 6         string cur2 = path[path.size()-1];
 7         if(cur1.size() > 1 && cur1[0] == '0' || cur2.size() > 1 && cur2[0] == '0') return false;
 8         string sum = add(cur1, cur2);
 9         if(sum==num.substr(pos, sum.length())) {
10             path.push_back(sum);
11             if(backtrack(num, pos+sum.length(), path)) return true;
12             path.pop_back();
13         }
14         return false;
15         
16     }
17     bool isAdditiveNumber(string num) {
18         vector<string> path;
19         for(int i=1; i<=num.size()/2; i++) {
20             path.push_back(num.substr(0, i));
21             for(int j=1; j<=(num.size()-i)/2; j++) {
22                 path.push_back(num.substr(i, j));
23                 if(backtrack(num, i+j, path)) return true;
24                 path.pop_back();
25             }
26             path.pop_back();
27         }
28         return false;
29     }
30 
31     //string + string = string 
32     string add(string a, string b) {
33         string sum;
34         int i = a.size()-1, j = b.size()-1, flag = 0;
35         while(i>=0 || j>=0) {
36             int s = flag + (i>=0?a[i]-'0':0) + (j>=0?b[j]-'0':0);
37             sum.insert(sum.begin(), s%10+'0');
38             flag = s/10;
39             i--,j--;
40         }
41         if(flag) sum.insert(sum.begin(), flag+'0');
42         return sum;
43     }
44 };