面试官:会玩牌吧?给我讲讲洗牌算法和它的应用场景吧!

本文介绍了面试中遇到的洗牌算法,它是一种随机算法,确保元素在序列中分布均匀。经典洗牌算法通过随机选择并放置元素实现,理论证明每个元素出现在任何位置的概率相等。JDK中ArrayList的shuffle方法提供了洗牌实现。洗牌算法应用广泛,如Eureka注册中心的负载均衡、音乐播放器的随机播放等。此外,文章提出两个扩展问题:大文件随机抽取一行和随机抽取多行的算法设计。
摘要由CSDN通过智能技术生成

点击上方蓝色字体,关注我 ——

一个在阿里云打工的清华学渣!

有一次参加面试,面试官问我:“会玩牌吧?”

内心:“咋滴,这是要玩德州扑克(或者炸金花),赢了他就能通过面试么?”

结果……

没想到面试官的下一句话:“给我讲讲洗牌算法以及它的应用场景吧!”

哈哈,以上内容纯属虚构

背景

本文产生背景是看到了 一枝花算不算浪漫 同学的这篇 Eureka注册中心集群如何实现客户端请求负载及故障转移?文章想到的。其实本人觉得那篇文中提到的负责均衡的重点就是本文要说的洗牌算法。

好了,回到题目上来。

这确实也是一道面试题,我曾经多次面试中都有遇到这个题目或者这个题目的变种。

你不妨花 1 秒,想想?

什么是洗牌算法

从名字上来看,就是给你一副牌让你洗呗,用怎样的方法才能洗得均匀呢?请大佬表演一下。

不好意思,翻车了

其实洗牌算法就是一种随机算法,你在斗地主的时候,随机把牌的顺序打乱就行。一个足够好的洗牌算法最终结果应该是可以让牌的顺序足够随机。好像有点绕~

这么来说吧,一副牌大家斗地主的话用 54 张(不考虑你们打配配牌的情形哈),那么这 54 张牌的顺序的话,按照排列组合算法,应该是有 54! 这么多种,然后你的洗牌算法就是从这 54! 种排列中,随机选 1 种。

无聊的石头算了一下,54 的阶乘有多大呢?大概就是这么大一长串数字,2308436973392413804720927448683027581083278564571807941132288000000000000L,准确答案看下图:

54的阶乘计算结果

我们还是以 4 张牌作为例子吧。

4 张牌,JQKA,所有的排列有 4!=4*3*2*1=24 种,分别如下:

('J', 'Q', 'K', 'A')
('J', 'Q', 'A', 'K')
('J', 'K', 'Q', 'A')
('J', 'K', 'A', 'Q')
('J', 'A', 'Q', 'K')
('J', 'A', 'K', 'Q')
('Q', 'J', 'K', 'A')
('Q', 'J', 'A', 'K')
('Q', 'K', 'J', 'A')
('Q', 'K', 'A', 'J')
('Q', 'A', 'J', 'K')
('Q', 'A', 'K', 'J')
('K', 'J', 'Q', 'A')
('K', 'J', 'A', 'Q')
('K', 'Q', 'J', 'A')
('K', 'Q', 'A', 'J')
('K', 'A', 'J', 'Q')
('K', 'A', 'Q', 'J')
('A', 'J', 'Q', 'K')
('A', 'J', 'K', 'Q')
('A', 'Q', 'J', 'K')
('A', 'Q', 'K', 'J')
('A', 'K', 'J', 'Q')
('A', 'K', 'Q', 'J')

那么,一个均匀的洗牌算法,就是每次洗牌完后,获得上面每种顺序的概率是相等的,都等于1/24。感觉已经出来了一种算法了,那就是先像前文所述把所有的排列情况都枚举出来,分别标上号 1-24 号,然后从 24 中随机取一个数字(先不考虑如何能做到随机取了,这个话题好像也没那么容易),获取其中这个数字对应的号的排列。

这个算法复杂度是多少?假设为 N 张牌的话,应该就是 1/N!(注意是阶乘,这里可不是感叹号),显然复杂度太高了。

有没有更好的方法呢?答案当然是肯定的。

经典的洗牌算法

洗牌算法实际上是一个很经典的算法,在经典书籍《算法导论》里面很靠前的部分就有讲解和分析。

我们把这个洗牌过程用更加“程序员”的语言描述一下,就是假设有一个 n 个元素的数组 Array[n],通过某种方式,随机产生一个另外一个序列Array'[n]让数组的每个元素 Array[i] 在数组中的每个位置出现的概率都是1/n

其实方法可以这样,依次从 Array 中随机选择 1 个,依次放到 Array' 中即可。证明一下:

  • Array[0],在新数组的第 0 个位置处的概率为:1/n,因为随机选,只能是1/n的概率能选中;

  • Array[1],在新数组的第 1 个位置处的概率为:1/n,因为 第一次没选中 Array[1]的概率为 n-1/n,再结合第二次(只剩下n-1个了,所以分母为n-1)选中的概率为:1/n-1,因此概率为:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值