Ai < Bj
の場合、それは真実でなければならないという観察を行いますAi < Bj-1
。一方、の場合Bj < Ai
、Bj < Ai-1
..どのようにそれがanyi
とに当てはまるのj
でしょうか?
とのすべてのペアに当てはまるわけではありませi
んj
。この記事は特別な状況を考慮しています。
A
まず、との共通要素の形式であっても、重複はないと想定されB
ます。第二に、
Ai < Bj ==> Ai < Bj-1, resp. Bj < Ai ==> Bj < Ai-1
どちらも_
Bj-1 < Ai < Bj resp. Ai-1 < Bj < Ai
保持します。したがって、これらの構成を除外し、すぐAi < Bj ==> Ai <= Bj-1
にBj < Ai ==> Bj <= Ai-1
従うと、厳密な不等式は、重複が存在しないという仮定に従います。
AiとBjとして識別されるAとBの中間要素を比較することにより、このトリッキーな問題にアプローチしようとします。AiがBjとBj-1の間にある場合、i + j+1の最小要素が見つかりました
配列B
には、j
よりも小さい要素がBj
あり、配列には、よりも小さい要素A
があります(インデックスは0から始まります)。したがって、の場合、両方の配列には、。よりも小さい要素が正確に含まれます。i
Ai
Bj-1 < Ai < Bj
j + i
Ai
重複がある場合はどうなりますか?
あまりない。
まだ状況を考えていi + j = k-1
ます。と仮定しましょうAi <= Bj
。
- もしも
Ai = Bj
?
- もしも
Ai < Bj
?
ケース1の場合、m
のような最小のインデックスAm = Ai
、およびn
のような最小のインデックスとしBn = Bj
ます。次に、両方の配列に、m + n <= i + j = k-1
厳密に。よりも小さい要素Ai
と、少なくとも。(i+1) + (j+1) = (k+1)
よりも大きくない要素がありAi
ます。したがって、k番目に小さい要素はに等しくなりAi
ます。
2.については、考慮すべき3つのケースBj-1 < Ai
、a)、b)Bj-1 = Ai
、c)がありBj-1 > Ai
ます。
a)の場合、以下のj
要素がB
ありAi
、それらはすべて厳密に小さく、(上記のように)厳密に小さいm <= i
要素と不明な数がありますが、少なくとも要素は。に等しくなります。したがって、両方の配列には、厳密に。よりも小さい要素が正確に存在し、少なくとも要素は。よりも大きくないため、両方の配列のk番目に小さい要素は一緒になります。A
Ai
m
i-m+1
Ai
j + m <= j + i = k-1
Ai
j + m + (i-m+1) = j+i+1 = k
Ai
Ai
b)の場合、同じ推論は、両方の配列のk番目に小さい要素が一緒に等しいことを示していAi
ます。
残りのケースではAi < Bj-1
、物事はほとんど複雑になりません。配列B
には少なくとも、以下のj
要素が含まれBj-1
、配列A
には少なくともi+1
厳密により小さい要素が含まれるBj-1
ため、両方の配列のk番目に小さい要素は最大で。になりBj-1
ます。ただし、より小さくすることはできませんAi
(よりも小さい要素B
を多く含むため、両方の配列に含まれるのは最大でよりも小さい要素です)。j-1
Ai
i + (j-1) = k-2
Ai
したがって、下の部分をAi
配列から破棄し、A
上の部分をBj-1
配列から破棄して、B
重複することなく続行できます。
変更されたのは、いくつかの厳密な不等式を弱い不等式に置き換える必要があるということだけでした。
コード(スライスする代わりに開始インデックスと長さを渡した方が効率的ですが、スライスするとコードが短くなります):
def kthsmallest(A, B, k):
if k < 1:
return None
a_len, b_len = len(A), len(B)
if a_len == 0:
return B[k-1] # let it die if B is too short, I don't care
if b_len == 0:
return A[k-1] # see above
# Handle edge case: if k == a_len + b_len, we would
# get an out-of-bounds index, since i + j <= a_len+b_len - 2
# for valid indices i and j
if a_len + b_len == k:
if A[-1] < B[-1]:
return B[-1]
else:
return A[-1]
# Find indices i and j approximately proportional to len(A)/len(B)
i = (a_len*(k-1)) // (a_len+b_len)
j = k-1-i
# Make sure the indices are valid, in unfortunate cases,
# j could be set to b_len by the above
if j >= b_len:
j = b_len-1
i = k-1-j
if A[i] <= B[j]:
if j == 0 or B[j-1] <= A[i]:
return A[i]
# A[i] < B[j-1] <= B[j]
return kthsmallest(A[i:], B[:j], k-i)
# B[j] < A[i], symmetrical to A[i] < B[j]
if i == 0 or A[i-1] <= B[j]:
return B[j]
# B[j] < A[i-1]
return kthsmallest(A[:i], B[j:], k-j)