スライディング ウィンドウ アルゴリズムの概要

序文

私はバグを書ける Zihan です。私の人生には終わりがなく、私のアルゴリズムは決して止まりません。
昨日の夜、何もすることがなく、学校の ACM チームのトレーニング コンピュータ ルームにしばらく行っていました。新入生が私を地面に押しつけたり、さすったりしてくれて、とても刺激的でした。スライディング ウィンドウ アルゴリズムを学びました。残念ながら、アルゴリズムのコースは始まったばかりで、以前から少し勉強したことがありますが、ほとんどブラッシュアップしていませんでした。今後、私は彼らと夜に練習に行くことが多くなりますが、この行為を「盗み」と呼びたいと思います。(マニュアルおかしい)

アルゴリズム的思考

個人的には、スライディング ウィンドウ アルゴリズムの考え方はダブル ポインタのアルゴリズムに似ていると思います。ウィンドウをシミュレートし、作成されたウィンドウが徐々にスライドします。質問で与えられた制約に従って、ウィンドウの境界が更新され、継続的にウィンドウが更新されます。質問で必要な値を更新します。ウィンドウが境界までスライドすると、アルゴリズムが終了すると必要な値が取得できることも意味します。一般的に、右側の境界線は能動的にスライドし、左側の境界線は受動的にスライドします。

ことわざにあるように、真実をテストするための唯一の基準は実践です。以下では、スライディング ウィンドウ アルゴリズムの実際の応用について深く理解するために、スライディング ウィンドウ アルゴリズムに関する 3 つの質問を取り上げます。

引き違い窓 I

引き違い窓 I

問題解決のアイデア

2つのポインタをウィンドウの境界として設定することにより、スライディングウィンドウをシミュレートしますが、ウィンドウの右側の境界の文字がすでにウィンドウ内に存在する場合、左側の境界を更新する必要があります。同時に部分文字列の最大長も更新され、右ポインタが文字列の末尾に移動した時点でウィンドウのスライドが完了し、その値が部分文字列の最大長の値となります。

コード

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
    string s;
    while(getline(cin,s))
    {
    
    
        int i=0,j=0,curlen=0,maxlen=0;
        if(s.length()==0)
        {
    
    
            cout<<0<<endl;
            return 0;
        }
        for(;j<s.length();j++)
        {
    
    
            curlen++;
            for(int k=i;k<=j;k++)//扫描有无重复字符
            {
    
    
                if(s[k]==s[j+1])//存在重复字符
                {
    
    
                    if(curlen>maxlen) maxlen=curlen;//更新值
                    i=k+1;//跳过重复字符
                    curlen=j-i+1;//更新值
                    break;
                }
            }
        }
        maxlen=curlen>maxlen?curlen:maxlen;//更新值
        cout<<maxlen<<endl;
    }
    return 0;
}

引き違い窓Ⅱ

ここに画像の説明を挿入します

問題解決のアイデア

ダブルポインタを 2 つ設定します。右のポインタがスライドします。値が m 以上の場合、値が更新されます。その後、左のポインタを m 未満にスライドします。右のポインタは上記の状態にスライドし続け、次の処理が行われます。右ポインタがウィンドウの境界にスライドすると、アルゴリズムが終了します。

コード

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
    int Start=0,End=0,sum=0;
    int res=10000000;
    int n,m;
    cin>>n;
    int a[n];
    for(int i=0; i<n; i++)
        cin>>a[i];
    cin>>m;
    while(End<n)//右指针未到达边界
    {
    
    
        sum+=a[End];//右指针滑动
        if(sum>=m)//出现大于等于m的情况
        {
    
    
            res=min(res,End-Start+1);更新值
            while(sum>=m&&Start<=End)
            {
    
    
                res=min(res,End-Start+1);更新值
                sum-=a[Start];
                Start++;//左指针移动
            }
        }
        End++;//不满足情况,右指针继续移动
    }
    if(res==10000000)
        cout<<0<<endl;
    else
        cout<<res<<endl;
    return 0;
}

111111

ここに画像の説明を挿入します

問題解決のアイデア

ダブルポインタを設定します。右ポインタはスライドします。1に遭遇するとスライドを続けます。0に遭遇すると、その時点でウィンドウ内の0の数が質問で与えられたmと等しいかどうかを判断します。等しい場合、左ポインタは削除されるまで移動し、新しい 0 のためのスペースを確保するために 0 に移動します。m未満の場合は右ポインタが動き続けます。その後、右ポインタがウィンドウ境界に移動するまで値が更新され、アルゴリズムが終了します。

コード

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
    int n,m,Max=0;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++)
        cin>>a[i];
    cin>>m;
    int left=0,right=0;
    for(;right<n;right++)
    {
    
    
        if(a[right]==0)
        {
    
    
            if(m==0)//到达限制条件
            {
    
    
                while(a[left]==1)
                    left++;
                left++;//去除一个0
            }
            else
                m--;
        }
        Max=max(right-left+1,Max);//更新值
    }
    cout<<Max<<endl;
    return 0;
}

おすすめ

転載: blog.csdn.net/pipihan21/article/details/114665832