我有一大堆我想按隨機順序迭代的元素。但是,我不能修改列表,也不想創建它的副本,因爲1)它很大,2)可以預期迭代被提前取消。Lazy Shuffle算法
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()
排列。
也許這可能會給你一個提示: 的http://計算器。com/questions/352203/generated-permutations-lazily – dsd 2013-04-23 09:05:13
答案似乎是Steinhaus-Johnson-Trotter算法,它迭代地生成所有排列。我正在尋找一個(隨機選擇的)排列,迭代構建。 – Cephalopod 2013-04-23 09:24:33
對此網站上的類似問題的回答建議使用具有可變塊大小的加密算法來加密序列0,1,2,... http://stackoverflow.com/a/18185810/154770 – 2013-10-02 04:40:38