Leetcode の難易度 —— 最大スライディング ウィンドウ (非常に詳細なアイデア、キューの有無にかかわらず合格可能)

(最近難しい問題をやっているのですが、コメントと同じようなものが多く、解答を書く気力がありません。この問題のコメントは全部キューに書かれていると思いますが、スルーしても問題ありません。キューがあるため、キューとキューなしのアイデアを使用して、それらを別々に書きました)

質問:
整数配列 nums があるとすると、配列の左端から右端まで移動するサイズ k のスライディング ウィンドウがあります。スライディング ウィンドウ内では k 個の数字のみが表示されます。スライディング ウィンドウは一度に 1 ビットずつのみ右に移動します。
スライディング ウィンドウの最大値を返します。

答え:

①キューを利用する

まずプライオリティキューを見ていきますが、ウィンドウを移動する際に左側の不要な値を削除するにはどうすればよいでしょうか? この時、プライオリティキューをsetで置き換えることができるので、セットが重ならないようにするにはどうすればよいでしょうか? deduplicated? ペアを使用して値と値を同時に保存できます。重複しないように下付き文字を付けます。次のステップは非常に簡単です。ウィンドウを移動するたびに、ウィンドウに新しい値を追加します。右に、左の不要な値を削除し、最大値を取得します。

typedef pair<int, int> P;
class Solution {
public:
    set<P> temp;
    vector<int> res;
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        for(int i = 0; i < k; i++) {
            temp.insert(make_pair(nums[i], i));
        }
        res.push_back(temp.rbegin() -> first);
        for(int i = k; i < nums.size(); i++) {
            temp.erase(make_pair(nums[i - k], i - k));  // 去除
            temp.insert(make_pair(nums[i], i));  添加
            res.push_back(temp.rbegin() -> first);   // 取范围最大值
        }
        return res;
    }
};

ただし、これは最適化できます。優先キューを使用して書き込むこともできます。詳細は追加値のサイズを考慮する必要がありますが、このコメント領域はいっぱいです。詳細については説明しません。コメント領域を参照してください。この質問

②行列なし

まず、この数値の -10 から 10 の 4 乗までの値の範囲を確認します。間違いなくここから開始することを検討できると思います。そうでない場合は、より大きな範囲を取ってみてはいかがでしょうか

次に、すべての数値の値の範囲である配列 data[20005] を構築します。次に、どのような種類の値をそこに格納するかを考慮する必要があります。

1. ウィンドウの現在の状況
2. アレイ全体の状況

最初のケースの場合、範囲内の値の数を配列に格納できますが、最大値を見つけるにはどうすればよいでしょうか? トラバース? 不可能です。タイムアウトする必要があります。セグメントツリーを使用しますか? いいえ、複雑さは上記とほぼ同じで、あまり意味がありません。

したがって、最初のケースを除外し、次に 2 番目のケースを検討します。その場合、各値の番号を保存するだけでなく、この時点では値の位置も非常に重要である必要があるため、値のすべてのインデックスを保存します (ベクターライブを使用)

では、この値を使ってどのように操作すればよいのでしょうか? 範囲の最大値を探しているので、この時点でのすべての値の最大値はその範囲内の最大値であり、2 番目に大きい値でなければならないと考えることができます。値は、最大値が存在する範囲内の他の範囲の最大値を除き、すべての範囲の最大値が決定されるまでこの順序で続行されます。解決策はありますか?

次のステップは操作方法です。現在の値は、前の大きい値があった範囲を繰り返しカバーすることはできません。その後、bool 配列を使用して、以前の大きい値でカバーされているかどうかを保存し、上書きされた値をスキップするだけです。各値は k 回とみなされ、非常に単純ですが、タイムアウトになります (プロテスト)

では、どうすればよいでしょうか? bool を使用して保存すると、情報を見逃して保存できなくなることを考慮する必要があります? ちなみに、bool を int に変更すると、現在位置が上書きされた後に最大位置を保存できます。この方法では、1 つずつたどる必要はなく、直接スキップできるため、指定された時間内に実行できます。

typedef pair<int, int> P;
class Solution {
public:
    int flag1 = 0;
    int flag2 = 0;
    vector<int> res;
    vector<int> ddd[20005];
    int mmm[100005];
    int fff[100005] = { 0 };
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        for(int i = 0; i < nums.size(); i++) {
            ddd[nums[i] + 10000].push_back(i);
            flag2 = max(flag2, nums[i] + 10000);
        }
        while(flag1 < nums.size()) {
            while(ddd[flag2].empty()) {
                flag2--;
            }
            int f = ddd[flag2][ddd[flag2].size() - 1];
            int p = 0;
            while(p < k && f < nums.size()) {
                if(fff[f] != 0) {
                    int temp = fff[f];
                    fff[f] = k - p;
                    p = p + temp;
                    f = f + temp;
                }
                else
                {
                    fff[f] = k - p;
                    mmm[f] = flag2 - 10000;
                    p++;
                    f++;
                    flag1++;
                }
            }
            ddd[flag2].pop_back();
        }
        for(int i = k - 1; i < nums.size(); i++) {
            res.push_back(mmm[i]);
        }
        return res;
    }
};

おすすめ

転載: blog.csdn.net/m0_52212261/article/details/128691202