私はアルゴリズムとデータ構造クラスの演習を行っています。基本的に、分割統治アルゴリズムまたは_check_distance
_と呼ばれる関数を実装して、リストX
の距離はk
以上で、このアルゴリズムの最悪の場合の複雑さはO(n*lg(n))
であることを示す必要があります。
最大でn*lg(n)
時間で漸近的に実行する必要があるアルゴリズムを考えるとき、マージソートについてすぐに考えます。マージソートは、まさに分割統治アルゴリズムです。使用しました。私の機能は正しいですか?
この演習の前は、すでに1つありました。リストに重複があるかどうかを確認するために、別のdivide and conquer関数を作成する必要がありました。この関数はO(n*lg(n))
でも実行する必要があります。
これは私の関数_check_duplicates
_で、merge sortアルゴリズムを再度使用します(merge sortアルゴリズム、これは典型的なマージソートなので、投稿したい場合は、質問してください!):
_def check_duplicate(X):
S = merge_sort(X) # O(n*lg(n))
for i in range(0, len(S) - 1): # O(n)
if S[i] == S[i + 1]:
return True
return False
_
私の最初の質問は次のとおりですそれは正しいですか、O(n * lg(n))時間で実行されますか?
ここで、実際の問題である2番目の関数に渡します。この関数は(前述のとおり)、リスト内の各要素間の距離が定数k
以上であることを確認する必要があります。この_check_distance
_関数では、上記の_check_duplicate
_関数を使用して、重複がないことを確認します。それ以外の場合は、すぐにfalseを返します。
さて、私のmain推論はリストをソートすることでした。リストがソートされると、ai + 1 要素は常にa以上になります私、したがって、すべての私X
、私 <= ai + 1 <= ai + 2、など.
さて、再び、すべてのために私X
では、私 + k、これはa以下i + 1の場合、すべての要素間の距離は> = k
である必要があります。
私は正しいですか?
_def check_distance(X, k):
if check_duplicate(X): # n*lg(n)
return False
else: # no duplicate values
A = merge_sort(X)
for i in range(len(A) - 1):
if A[i] + k > A[i + 1]:
return False
return True
_
私が正しくない場合、より良いアプローチがありますか?
これはもう必要ないと思いますが、私はこれについて考えた後で初めてgnasherのバンプに気づいたので、とにかくここにいくつかの私見の良いコードを残しておきます。
def check_distance(X, k):
A = merge_sort(X)
return all(b-a >= k for a, b in Zip(A, A[1:]))
先生の解決策に興味があります。彼はこの頭の痛い並べ替えと掃引だけを念頭に置いていたのでしょうか、それとももっと興味深いものですか?
明らかな解決策は、配列をO(n log n)でソートすることです。その後、要素をO(n)で順次チェックできます。彼が「分割統治」アルゴリズムを求めたとき、教師の心はどうなっているのだろう。
check_duplicate
は冗長です。並べ替えは要素を並べ替えるため、リストを並べ替えないでください。
2つの連続する要素間の差を計算し、その値をk
と比較します。
def check_distance(x, k):
l = len(x)
if l in [0,1]:
return False
for i in range(l-1):
if x[i+1] - x[i] < k:
return False
return True
再帰を使用して、
def check_dist(x,k):
l = len(x)
if l == 2:
return x[1] - x[0] >= k
if l in (0,1):
return False
return x[1] - x[0] >= k and check_dist(x[1:],k)