LeetCode:306. 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.
For example:
“112358” is an additive number because 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
“199100199” is also an additive number, the additive sequence is: 1, 99, 100, 199.
1 + 99 = 100, 99 + 100 = 199
Note: Numbers in the additive sequence cannot have leading zeros, so sequence 1, 2, 03 or 1, 02, 3 is invalid.
Given a string containing only digits ‘0’-‘9’, write a function to determine if it’s an additive number.
Follow up:
How would you handle overflow for very large input integers?
思路:剛一看這個題的時候沒有思路,知道應該是用dfs或backtracking一類的演算法,但是不知道如何下手,只好看答案,看了答案之後恍然大悟,其實很簡單。
解題的關鍵在於確定前兩個數,只要確定了前兩個數,後面的數可以依次計算出來,要麼符號條件要麼不符合條件。那麼如何確定前兩個數?
首先分析如何確定第一個數,第一個數的最小的長度是1(只包含一個數字),最大的長度是(L-1)/2,其中L為字串的長度,最大的長度一定小於總長度的一半,比如如果總長度是5,第一個數長度不能超過2,如果總長度是6,第一個數長度也不能超過2,所以最大的長度是(L-1)/2,。
再確定第二個數的範圍,第二個數從第一個數後面開始,第三個數從第二個數後面開始,我們首先知道,第三個數肯定至少和第一個數與第二個數一樣大,因為是和嘛,若第二個數從i開始到j-1結束,那麼第三個數長度最大為L-j,這個長度一定大於等於第一個數和第二個數長度的較大者,即:L-j>=i && L-j>=j-i。
確定了第二個數的範圍之後問題就簡單了,看看能不能構成加法序列,只要判斷剩下的字串是不是以sum開頭即可,然後遞迴判定,程式碼如下:
//這題的關鍵在於找前兩個數,前兩個數確定了,後面的依次判斷即可
//第一個數肯定從0開始,但最長是(L-1)/2,第二個數從第一個數後面開始,第三個數至少跟第一個和第二個較大的數一樣長
public boolean isAdditiveNumber(String num) {
int L = num.length();
//確定第一個數,最終用num.subStr(0,i)來確定第一個數,所以i可以用來標示第一個數的長度,
//但是下標i不包含在第一個數中
for(int i=1;i<=(L-1)/2;i++){
//如果長度大於等於2,則不能以0開頭
if(num.startsWith("0") && i>=2) break;
//確定第二個數,第一個數用num.subStr(i,j),包括i,不包括j,所以長度為j-i,
//第三個數從下標j開始,長度最長為L-1-j+1,即L-j
for(int j=i+1;(L-j)>=i && (L-j)>=j-i;j++){
if(num.charAt(i)=='0' && j-i>=2) break;
long num1 = Long.parseLong(num.substring(0,i));
long num2 = Long.parseLong(num.substring(i,j));
if(isAdditive(num.substring(j), num1, num2)){
return true;
}
}
}
return false;
}
//判斷由num1,num2和後續的字串能否構成加法序列
public boolean isAdditive(String remain,long num1,long num2){
if(remain.equals("")) return true;
long sum = num1+num2;
String sumStr = ""+sum;
if(!remain.startsWith(sumStr)) return false;
return isAdditive(remain.substring(sumStr.length()), num2, sum);
}