码迷,mamicode.com
首页 > 其他好文 > 详细

洗牌问题

时间:2020-05-14 23:53:40      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:random   算法   res   car   shuff   复杂度   测试用例   dup   object   

题目内容

题目: 手里面n张不同牌面的牌,编写一个洗牌程序,让随机取出一张牌的概率相同。

要求: 说明算法思路、分析时间复杂度、用Array编写洗牌程序、编写测试用例。

算法思路

技术图片

时间复杂度


??时间复杂度应该为:O(n)

实现程序

下面给出4种实现方法、比较各种方法的好坏,其中shuffle_best(cards)是上面算法分析的实现。

import random
def shuffle_system(cards):
    random.shuffle(cards)  # 官方给你的shuffle函数
import random
def shuffle_1st(cards):
    for k in range(len(cards)):
        i = random.randint(0,len(cards)-1) # 随机取出一张
        j = random.randint(0,len(cards)-1) # 随机取出一张
        cards[i], cards[j] = cards[j], cards[i] # 两张交换
import random
def shuffle_2nd(cards):
    for k in range(len(cards)):
        i = random.randint(0,len(cards)-1) # 随机取出一张
        cards[i], cards[k] = cards[k], cards[i] # 两张交换
    

最好的解法:
?? ??randomi = ?i + random.randint(0,(len(cards) - i -1)) ,此处 i +保证了前面放好的了牌不会被取到。

import random
def shuffle_best(cards):
    for i in range(len(cards)):  
        randomi =  i + random.randint(0,(len(cards) - i -1)) # 从剩下的随机取出一张
        cards[i], cards[randomi] = cards[randomi], cards[i] # 依次取出的和从剩余中随机取出的交换
   

测试用例

def test_shuffle(f):
    result = [[0 for i in range(0,10)] for j in range(0,10)]
    
    for i in range(10000):
        A = [i for i in range(0,10)]
        f(A)
        for j in range(len(A)):
            result[A[j]][j] += 1 # 第j张牌在第j个位置
    print("\n".join([‘‘.join([‘{:6}‘.format(item) for item in row])for row in result]))

技术图片
用官方给出的shuffle接口,每张牌出现的概率大都为1/10,符合要求。
技术图片
第一种洗牌程序,主对角线上的概率为2/10,不是很理想。
技术图片
第二种洗牌程序,主对角线下面的元素也不是很理想,我们想要的是都在1000次左右。
技术图片
第三种洗牌程序,每张牌在每个位置出现的位置的次数都接近1000,相比1st 和 2nd 的情况要好一点,是我们想要。


洗牌问题

标签:random   算法   res   car   shuff   复杂度   测试用例   dup   object   

原文地址:https://www.cnblogs.com/sinlearn/p/12892126.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!