トピック:
S = "123456579"などの数値文字列Sが与えられると、フィボナッチのようなシーケンスに分割できます[123、456、579]。
正式には、フィボナッチ数列は非負の整数のリストFであり、次の条件を満たす。
- 0 <= F [i] <= 2 ^ 31-1(つまり、各整数は32ビットの符号付き整数型に準拠します)。
- F.length> = 3;
- すべての0 <= i <F.length-2に対して、F [i] + F [i + 1] = F [i +2]が成り立ちます。
さらに、文字列を小さなブロックに分割する場合、ブロック自体が0でない限り、各ブロックの番号はゼロで始まってはならないことに注意してください。
Sから分割されたフィボナッチのようなシーケンスブロックのセットを返します。分割できない場合は[]を返します。
例1:
入力: "123456579"
出力:[123,456,579]
ソース:
問題解決のアイデア:バックトラック
文字列[start、i]の値を記録する変数nを定義します。最初の再帰(start = 0)のforループは次のとおりです。
- 再帰的終了条件:デジタル文字列処理が完了しました
- 結果は次の条件を満たす:デジタル文字列処理が完了し、結果が少なくとも3つの数値である
- 剪定条件:1つを見つけた後、または数値がintの最大値を超えた後、またはフィボナッチ式が満たされていない(判断を追加することもできます:現在の2つの数値の合計が現在の数値nより小さい場合は、forを終了します次の数が大きいため、ループします)
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();
}
}
}
};
各ブロックの数はゼロで始まってはなりません。この状況が処理されない場合、実際に通過する可能性があります。例:11203は[]を返す必要がありますが、このコードは[1,1,2,3]を返します。
解決策は、int sz = path.size();の後に行を追加することです。if(sz> 1 && s [start] == '0')break;は、シーケンスが少なくとも2つの数値の場合、開始することを意味します。は、指定された数値を0にすることはできません。0の場合は、スキップしてください。