ダブルポインタとは、オブジェクトをトラバースするプロセスで、アクセスに単一のポインタを使用する代わりに、同じ方向(高速ポインタと低速ポインタ)または反対方向(衝突ポインタ)の2つのポインタを使用してスキャンすることを指します。対応する目的。
例:
AcWing799。最長の連続した非反復サブシーケンス
長さnの整数列が与えられた場合、繰り返される数値を含まない最長の連続区間を見つけて、その長さを出力します。
方法:
配列visを開いて、区間[i、j]に現れた数を記録します。iが前に進むと、visが見つかった場合は区間vis [a [i]] ++にa [i]を追加します。 [a [i]]> 1、つまり、区間内でのa [i]の出現数が1より大きい場合(つまり、繰り返される数がある場合)、左ポインターjが後方に移動し、 vis [a [j]]-、jが1つ戻ると、jが指すa [j]は、vis [a [i]] == 1になるまで、区間[j、i]に存在しなくなり、jは停止します。移動、この時点でansを更新し、間隔の最大長を記録します
const int N = 1e5+5;
int n,a[N],vis[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0;
for(int i=1,j=1;i<=n;i++)
{
vis[a[i]]++;
while(vis[a[i]]>1) vis[a[j++]]--;//等价于vis[a[j]]--,j++;
ans=max(ans,i-j+1);
}
cout<<ans<<endl;
return 0;
}
例:
AcWing800。配列要素のターゲット合計
昇順でソートされた2つの順序付けられた配列AとB、およびターゲット値xが与えられます。配列インデックスは0から始まります。
A [i] + B [j] = xを満たす数のペア(i、j)を見つけてください。
データには独自のソリューションが保証されています。
練習:
問題は、配列が昇順で配置されるようにすることです。この単調性は、二重ポインターを使用して使用できます。ポインターiはA配列の先頭を指し、ポインターjはBの末尾を指します。配列を作成し、チェックを開始します。a[i] + b [j]> xの場合、配列の単調性のため、jはj--; a [i] + b [j] <xの場合は前方に移動する必要があります。 、同じ、私は1つ後ろに移動する必要があります、i ++; a [i] + b [j] == xの場合、(i、j)を出力して中断できます
const int N = 1e5+5;
int n,m,x,b[N],a[N];
int main()
{
cin>>n>>m>>x;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++) cin>>b[i];
for(int i=0,j=m-1;i<n;i++)
{
while(j>=0&&a[i]+b[j]>x) j--;
if(a[i]+b[j]==x)
{
cout<<i<<" "<<j<<endl;
break;
}
}
return 0;
}
次のように書くこともできます。
const int N = 1e5+5;
int n,m,x,b[N],a[N];
int main()
{
cin>>n>>m>>x;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++) cin>>b[i];
int i=0,j=m-1;
while(i<n&&j>=0)
{
if(a[i]+b[j]==x) break;
else if(a[i]+b[j]>x) j--;
else if(a[i]+b[j]<x) i++;
}
cout<<i<<" "<<j<<endl;
return 0;
}
例:
AcWing2816 。サブシーケンスを判断する
長さnの整数a1、a2、...、anのシーケンス、および長さmの整数b1、b2、...、bmのシーケンスが与えられます。
シーケンスがbシーケンスのサブシーケンスであるかどうかを判断してください。
サブシーケンスとは、アイテムの一部を元の順序で並べて得られたシーケンスのことです。たとえば、シーケンス{a1、a3、a5}は、シーケンス{a1、a2、a3、a4、a5}のサブシーケンスです。
方法:
aがbのサブシーケンスであるかどうかを判別する必要があるため、ポインターiを配列の先頭を指すように設定し、ポインターjをb配列の先頭を指すように設定してから、b配列
をトラバースできます。 、現在のa [i]がb [j]と同じであるかどうかを判断するたびに、a [i] == b [j]の場合、i ++;
最後のトラバースの後、iがnに等しいかどうかを判断します。等しい場合は、配列内の各番号がb配列内で順番に並んでいる可能性があることを意味します。見つかった場合は「はい」を出力し、そうでない場合は「いいえ」を出力します。
const int maxn = 1e5+5;
int n,m;
int a[maxn],b[maxn];
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++) cin>>b[i];
int i=0,j=0;
while(i<n&&j<m)
{
if(a[i]==b[j]) i++;
j++;
}
if(i==n) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}