ランダムな順序で反復したい要素の大きなリストがあります。ただし、リストを変更することはできず、リストのコピーも作成したくありません。1) サイズが大きく、2) 反復が早期にキャンセルされることが予想されるためです。
List<T> data = ...;
Iterator<T> shuffled = shuffle(data);
while (shuffled.hasNext()) {
T t = shuffled.next();
if (System.console().readLine("Do you want %s?", t).startsWith("y")) {
return t;
}
}
System.out.println("That's all");
return t;
O(n)
上記のコードが実行される(そしてできればスペースのみを必要とする)アルゴリズムを探しているO(log n)
ので、以前に生成された要素をキャッシュすることはオプションではありません。アルゴリズムが偏っているかどうかは気にしません (明らかでない限り)。
(私の質問では疑似 Java を使用していますが、必要に応じて他の言語を使用することもできます)
これが私がこれまでに得た最高のものです。
Iterator<T> shuffle(final List<T> data) {
int p = data.size();
while ((data.size() % p) == 0) p = randomPrime();
return new Iterator<T>() {
final int prime = p;
int n = 0, i = 0;
public boolean hasNext() { return i < data.size(); }
public T next() {
i++; n += prime;
return data.get(n);
}
}
}
、定数空間ですべての要素を反復しますが、順列O(n)
しか生成できないため、明らかに偏っています。data.size()