まず、例を見る前に、一般的に使用されるアルゴリズムである定規法を紹介します。
ルーラーの概念:
2つのポインターと2つのポインターとも呼ばれる定規法は、アルゴリズムの競合で一般的に使用される最適化手法であり、シーケンス間隔の問題を解決するために使用されます。シンプルな操作と簡単なプログラミング。簡単に言うと、二重ループを単一ループに変換できるため、時間計算量がO(n 2)からO(n)に増加します。
栗を取る:
まず、iとjで実行される二重ループを見てください。
for(int i = 0; i < n; i++) //i从头扫到尾
for(int j = n-1; j >= 0; j--){
//j从尾扫到头
......
}
ここで、iは0からn-1にループし、jはn-1から0にループします。これら2つのループの時間計算量はO(n 2)です。
ルーラーメソッドはi、jをループで一緒に処理できます。コードは次のとおりです。したがって、複雑さはO(n 2)からO(n)に変更されます。
for (int i = 0, j = n - 1; i < j; i++, j--) {
......
}
while()を書く別の方法があります:
//用while实现:
int i = 0, j = n - 1;
while (i < j) {
//i和j在中间相遇。这样做还能防止i、j越界
...... //满足题意的操作
i++; //i从头扫到尾
j--; //j从尾扫到头
}
上記は単なる逆スキャンであり、別の同じ方向のスキャンに悩まされています。
ブルーブリッジカップのボスが要約を作成しました。以下を見て理解してください。
円形ポインタiとjはスキャンます。定規方式では、これら2つのポインタiとjには2つのスキャン方向があります。iとjを反対方向に
逆スキャンします。iは最初から最後まで、jは最後から最後までです。初めに、真ん中のミートで。逆方向にスキャンされたiおよびjポインターは、左ポインターおよび右ポインターと呼ばれることもあります。
iとjを最初から最後まで同じ方向にスキャンしますが、速度は異なります。たとえば、jはiの前を走ることができます。同じ方向にスキャンされたiポインターとjポインターは、高速ポインターと低速ポインターとも呼ばれます。このとき、iとjの速度が異なるため、iとjの間のシーケンスで可変サイズのスライディングウィンドウが生成されます。ルーラー方式の利点です。柔軟なアプリケーションがあります。
ルーラーを使用する上で最も重要なことは、2つのポインターiとjが全体で1つのサイクルしか持てないことです。たとえば、iは1回サイクルし、対応するjはiサイクルを1回しか追跡できません。このようにして、O(n 2)からO(n)への計算の複雑さの最適化を実現できます。
次は、C++定規メソッドに似たpythonviolenceメソッドを使用した、州の競争における実際の質問です。
トピックの説明
XiaoMingはプログラマーフォーラムを維持しています。現在、彼は合計N行の「いいね」のログを収集しています。各行の形式は次のとおりです。
ts id
時間tsの番号idの投稿が「いいね」を受け取ったことを示します。
Xiao Mingは、かつて「ホットな投稿」だった投稿を数えたいと考えています。投稿が長さDのいずれかの期間にK件以上のいいねを受け取った場合、XiaoMingはその投稿を「ホット投稿」と見なします。
具体的には、[T、T + D)の期間内に投稿がK件以上のいいねを受け取ることを満足する特定の瞬間Tがある場合(左閉と右開の間隔にあることに注意してください)、投稿かつては「ホットな」投稿でした。
ログを考慮して、Xiaomingが「ホット投稿」であったすべての投稿番号をカウントするのを手伝ってください。
説明を入力してください
最初の行には、3つの整数N、D、Kが含まれています。
次のN行には、1行に1つのログが含まれ、2つの整数tsとidが含まれています。
中、1 <= K <= N <= 10 5、0 <= ts <= 10 5、0 <= id <= 105。
出力の説明
ホットポストIDを昇順で出力します。IDごとに1行。
サンプル入力
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
サンプル出力
1
3
詳細な回答
上記でルーラーメソッドを紹介しましたが、これは理解として使用できます。この質問でPythonを使用するブルートフォースメソッドは、c ++ルーラーメソッドとほぼ同じ複雑さであるため、ここでは最初にpythonブルートフォースメソッドを使用します(コードは簡単に書くことができます、hehe):
from bisect import bisect_left
maxn=int(1e5+50)
n,d,k=map(int,input().split())
m=[[] for _ in range(maxn)]
post=set()
for _ in range(n):
ts,idd=map(int,input().split())
post.add(idd)
m[idd].append(ts) #读每个帖子的赞的时间
post = sorted(post) #对帖子id排序
for idd in post: #检查每个帖子
m[idd]=sorted(m[idd]) #把某个帖子的ts排序
for i in range(len(m[idd])): #暴力统计这个帖子是不是热帖
td = m[idd][i]+d
if(bisect_left(m[idd],td)-i >= k):
print(idd)
break