web-dev-qa-db-ja.com

O(n * lg(n))の数値リストのすべての要素間の距離をチェックします

私はアルゴリズムとデータ構造クラスの演習を行っています。基本的に、分割統治アルゴリズムまたは_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
_

私が正しくない場合、より良いアプローチがありますか?

2
nbro

これはもう必要ないと思いますが、私はこれについて考えた後で初めてgnasherのバンプに気づいたので、とにかくここにいくつかの私見の良いコードを残しておきます。

def check_distance(X, k):
    A = merge_sort(X)
    return all(b-a >= k for a, b in Zip(A, A[1:]))

先生の解決策に興味があります。彼はこの頭の痛い並べ替えと掃引だけを念頭に置いていたのでしょうか、それとももっと興味深いものですか?

2
Stefan Pochmann

明らかな解決策は、配列をO(n log n)でソートすることです。その後、要素をO(n)で順次チェックできます。彼が「分割統治」アルゴリズムを求めたとき、教師の心はどうなっているのだろう。

1
gnasher729

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)
0
Nizam Mohamed