[再帰] [leetcode]注文時間

トピック:

「順序の順序」を次のように定義します。各桁の数値は、前の桁の数値より1大きい整数です。

[低、高]の範囲のすべての注文番号で構成される注文リスト(最小から最大の順に並べ替え)に戻ってください。

例1:

出力:低= 100、高= 300
出力:[123,234]
例2:

出力:低= 1000、高= 13000
出力:[1234,2345,3456,4567,5678,6789,12345]

ソース:

1291.ストレートタイム

問題解決のアイデア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には従うべきルーチンがなく、合格するには繰り返しデバッグする必要があります。おそらくより効率的に実行されますが、実装が複雑で書き込みに時間がかかるため、お勧めしません。

おすすめ

転載: blog.csdn.net/hbuxiaoshe/article/details/115244698