web-dev-qa-db-ja.com

これは、O(n * log(n))よりも速いソートアルゴリズムですか?

N個の変数があり、それぞれにm個の可能な値がある場合。 (整数の場合、mは20億の何かです。)

まず、可能なすべての値を0からm-1までの整数に順番にマッピングします。そして、マッピング関数を定義します。

index(v): value to integer
value(i): integer to value

次に、n個の変数をループし、すべての値が出現した回数を数えます。

for v in variables {
    counter[index(v)] += 1
}

最後に、counter配列をループして、結果の配列に値を入れます。

for i in 0...m-1 {
    for j in 1...counter[i] {
        result.append(value(i))
    }
}

結果の配列はソートされ、このアルゴリズムの複雑さはO(n + m)です。

大きいnと小さいmの場合、O(n * log(n))よりも優れている可能性があります。

3
Jeffrey Chen

おめでとうございます、あなたはcounting sortを再発明しました! (私は皮肉ではありません、物事が独立して何度も再発明されていることは良いことであり、問​​題を解決する自然で良い方法であることを示しています。)

ソートのカウントの時間の複雑さは、確かにO(n * log n)よりも優れています。 「ソート」のために通常引用されるΩ(n * log n)の「バリア」はwrongであることに注意してください。これは比較ベースのソートの下限であり、notallソートの下限です。

特に、ソートのカウントは比較に基づいていないため、比較ベースのソートの下限は適用されません。

13
Jörg W Mittag

nが大きい場合、log(n)は明らかに1より大きく、n * log(n)はnより大きい。 mnと比較して非常に小さい場合、O(n + m)O(n)に近い。したがって、これらの特定の条件では、アルゴリズムが高速になります。

しかし、この優れた時間パフォーマンスは、スペースパフォーマンスを犠牲にしています。

0
Christophe