トピック:
「順序の順序」を次のように定義します。各桁の数値は、前の桁の数値より1大きい整数です。
[低、高]の範囲のすべての注文番号で構成される注文リスト(最小から最大の順に並べ替え)に戻ってください。
例1:
出力:低= 100、高= 300
出力:[123,234]
例2:
出力:低= 1000、高= 13000
出力:[1234,2345,3456,4567,5678,6789,12345]
ソース:
問題解決のアイデア1:再帰
この質問を取得します。最初の反応は再帰です。バックトラッキングコードを見てください。あなたは尋ねるかもしれません:なぜバックトラッキングを呼び出さないのですか?この質問では、再帰関数の可能性は1つだけです。たとえば、現在の数値は12であり、次の数値は124ではなく123である必要があるため、バックトラックはありません。
再帰を使用する際の注意点:
- 結果は順序が狂っており、並べ替え後に出力する必要があります
- 数が10に達したときの治療に注意してください
class Solution {
public:
vector<int> result;
vector<int> sequentialDigits(int low, int high) {
for (int i = 1; i < 10; i++) {
int path = i;
back(path, i+1, low, high);
}
sort(result.begin(), result.end());
return result;
}
void back(int path, int next, int low, int high) {
if (path >= low) {
result.push_back(path);
}
if (next == 10) return;
path = path * 10 + next;
if (path <= high) {
back(path, next+1, low, high);
}
}
};
問題解決のアイデア2:賢いアイデア
すべてのシーケンス時間を事前に定義し、トラバースするだけで、コードは説明なしで簡単になります。
class Solution {
public:
vector<int> sequentialDigits(int low, int high) {
vector<int> result;
int nums[36] = {
12,23,34,45,56,67,78,89,
123,234,345,456,567,678,789,
1234,2345,3456,4567,5678,6789,
12345,23456,34567,45678,56789,
123456,234567,345678,456789,
1234567,2345678,3456789,
12345678,23456789,
123456789};
for (int i = 0; i < 36; i++) {
if (nums[i] >= low && nums[i] <= high) {
result.push_back(nums[i]);
}
}
return result;
}
};
問題解決のアイデア3:法
アイデア2によると、numsは最初の行から始まり、数の幅は2、3、4、5、6、7、8、9です。可変幅を定義して、数値の幅を記録します。これは、2または数値の幅の下限から開始できます。
同じ幅の下で、番号ウィンドウをスライドして、現在の番号に基づいて次の番号を取得します。計算方法は、次の例に示されています。
- width = 3の場合、現在の数値が234の場合、次の数値は(2345)%1000 = 345です。
- width = 5の場合、現在の番号が23456の場合、次の番号は(234567)%100000 = 34567です。
width + 1、mod = mod * 10の場合は常に、上記の1000、100000を記録する変数modを定義します。
現在の数値が高い場合、トラバーサルは終了します。
class Solution {
public:
vector<int> sequentialDigits(int low, int high) {
vector<int> result;
int width = 0; // 位数
int t = low;
long mod = 1;
while (t > 0) {
width++;
t /= 10;
mod *= 10;
}
while (width < 10) {
bool end = false;
long sum = 0; // width组成的数字
int n = 1;
for (; n < width; n++) sum = sum * 10 + n; // 前width-1组成的数字
for (; n < 10; n++) {
sum = (sum * 10 + n) % mod;
if (sum > high) {
end = true;
break;
}
if (sum >= low) {
result.push_back(sum);
}
}
if (end) break;
width++;
mod *= 10;
}
return result;
}
};
総括する:
私はアイデア1と2が好きです。言うまでもなく、アイデア2は、実装が簡単なレトロスペクティブルーチンに従って作成できます。
アイデア3には従うべきルーチンがなく、合格するには繰り返しデバッグする必要があります。おそらくより効率的に実行されますが、実装が複雑で書き込みに時間がかかるため、お勧めしません。