2017-07-30 3 views
1

いくつかを読んだ後、私はthis answerは一般的に受け入れられたことを見て、SOの質問「どのようにシャッフルする」:シャッフル機能の欠点は何ですか?

function shuffle (array) { 
    var tmp, current, top = array.length; 

    if(top) while(--top) { 
     current = Math.floor(Math.random() * (top + 1)); 
     tmp = array[current]; 
     array[current] = array[top]; 
     array[top] = tmp; 
    } 

    return array; 
} 

しかし、問題は、単にランダムにリストの要素を選ぶと何でしょう、like I posted

function shuffle (array) { 
    var result = []; 
    while(array.length){ 
    var index = Math.floor(Math.random() * array.length); 
    result.push(array.splice(index, 1)[0]); 
    } 
    return result; 
} 
+0

インデックスは毎回ユニークではないかもしれません。 – Durga

+0

@Durgaそれは問題ではありません。それは – Li357

+0

の後に選択されないように値をスプライスしています。これはあなたのメソッドを含む本当に素晴らしい説明です:https://bost.ocks.myke/shuffle/ –

答えて

2

あなたの答えによって指定された結果に何か問題があるように思えません、あなたがランダムなインデックスを拾うとして、配列をシャッフルして、結果の配列にプッシュするように見えるん。

2つのアプローチの違いは、最初の解はO(n)の最悪ケースの複雑さを持ち、解は最悪ケースのO(n^2)の最悪ケースの時間複雑さです。 O(n)の複雑さであり、O(n)を取るwhileループがあり、第2のアプローチもO(n)の空間複雑さを有する。

+0

ありがとうございます。あなたは、質問の2つのシャッフル機能が非常に似ていることを私に気付かせてくれました。 –

0

元の配列をと呼び出す前に、元の配列を保存するためにwhileループの前に呼び出すことができます。

function shuffle (array) { 
    var result = []; 
    var temp = array.slice(0); 
    while(temp.length){ 
    var index = Math.floor(Math.random() * temp.length); 
    result.push(temp.splice(index, 1)[0]); 
    } 
    return result; 
} 
+1

不利な点は効率です。私はスプライシングがここで最高の操作であるかどうかは分かりません。私が考える前者ほど効率的ではありません。 – Li357

+0

@AndrewLi各アプローチのベンチマークを作成して推測を避けることができます – guest271314

+0

各アプローチの時間の複雑さはそれ自体で言います。スプライシングはO(n)なので、反復とスプライシングはO(n * n)になります。ほんの少しのループと配列のアクセスはO(n * 1)になります。 – Li357

0

明らかな問題は、あなたのソリューションが新しいresult配列を構築している間に、引数arrayを空にしてしまうことです。これは絶対的な悪い習慣です。引数を不必要に変更しないでください。また、を使用すると、削除された要素の後ろのすべての要素を移動するため、かなり非効率的です。

関連する問題