普林斯顿公开课 算法2-5:洗牌算法
来源:互联网 发布:2016网络诈骗案破案率 编辑:程序博客网 时间:2024/05/15 23:54
洗牌就是将已经排序好的数列打乱顺序
第一种方法
基本想法就是给每个元素标注一个随机的小数,然后再对序列进行排序。但是这种方法的开销比排序算法还要高。
目标
寻找一个线性复杂度的洗牌算法。
Knuth排序
将原始序列分成A B两个序列,A序列表示已经乱序,B序列表示尚未乱序。
步骤
将B序列的第一个元素取出,加入到A序列的末尾
从A序列中随机取出一个元素,与末尾的元素互换
循环直到B序列中没有元素为止
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import
java.util.Random;
public
class
Shuffle {
public
static
void
shuffle(Object[] li) {
Random r =
new
Random();
for
(
int
i=
0
;i<li.length;i++){
int
b=r.nextInt(i+
1
);
// 注意这里使用nextInt(i+1),而不是nextInt(i)或nextInt(n+1)
Object temp = li[b];
li[b] = li[i];
li[i] = temp;
}
}
}
洗牌故事
某在线纸牌游戏的洗牌算法是这样的:
for
i :=
1
to
52
do
begin
r := random(
51
) +
1
;
swap := card[r];
card[r] := card[i];
card[i] := swap;
end
;
这里有多个BUG
随机数不会随到最后一张卡片
乱序不是均匀的,取随机数应当是random(i),而不是random(51)
random()使用2^32的整数作为种子,因此有2^32种洗牌结果
seed=从0点到现在的毫秒数,因此只有8640万种洗牌结果
根据这些BUG,攻击者只要知道5张牌的顺序,时间与服务器同步,就可以实时计算出后续所有的卡片了。
最好的洗牌方法
有煽值高的随机数源,比如随机数硬件
经常检查随机数是否符合统计学规律,因为随机数硬件坏了之后是完全没有症状的
采用均匀的洗牌算法
最后,要说明一点洗牌算法不是那么简单的。
0 0
- 普林斯顿公开课 算法2-5:洗牌算法
- 普林斯顿公开课 算法1-2:观察
- 普林斯顿公开课 算法2-7:栈
- 普林斯顿公开课 算法2-9:队列
- 普林斯顿公开课 算法2-10:泛型
- 普林斯顿公开课 算法2-11:迭代器
- 普林斯顿公开课 算法1-5:算法理论
- 普林斯顿公开课 算法2-2:选择排序
- 普林斯顿公开课 算法2-1:排序概述
- 普林斯顿公开课 算法2-3:插入排序
- 普林斯顿公开课 算法2-4:希尔排序
- 普林斯顿公开课 算法2-6:凸包
- 普林斯顿公开课 算法2-8:调整数组大小
- 普林斯顿公开课 算法4-2:二叉堆
- 普林斯顿公开课 算法1-3:数学模型
- 普林斯顿公开课 算法1-6:内存
- 普林斯顿公开课 算法3-3:三路快排
- 普林斯顿公开课 算法1-1:算法分析
- linux中 find grep组合使用示例
- 苹果WWDC14-----iOS8新特性
- 文件 软链接和硬链接
- EJB3.0+Struts2结合登陆小案例
- 用InputStreamWriter/Reader实现对文件的存取操作
- 普林斯顿公开课 算法2-5:洗牌算法
- mysql插入不重复记录
- 新辰:当前互联网形势下 SEOer该何去何从?
- 指针申请内存
- Ch5优化时间和空间效率——31:连续子数组的最大和
- 外部变量申明
- Android vibrator
- 用文件保存的学生名单
- Java多线程编程总结