程序员面试金典——解题总结: 9.18高难度题 18.2编写一个方法,洗一副牌。要求做到完美洗牌,换言之,这副牌52!种排列组合出现的概率相同

完美洗牌算法
本文介绍了一种使用递归实现的完美洗牌算法,确保每张牌都有相同的概率出现在任何一个位置,实现了52张牌所有可能排列的概率相等。通过递归调用自身函数打乱前n-1张牌,并随机选取一个位置与第n张牌交换,从而达到完美洗牌的目的。
#include <iostream>
#include <stdio.h>
#include <vector>
#include <sstream>

using namespace std;
/*
问题:编写一个方法,洗一副牌。要求做到完美洗牌,换言之,这副牌52!种排列组合出现的概率相同。假设给定一个完美的
     随机数发生器。
分析:之前的洗牌方式是,遍历52张牌,对当前牌i,获取1到52中的随机数index,将牌i和牌index进行调换。
      这个方法是否符合52!概率相同?这个应该是符合的
	  递归的方式就是:假设shuffle()对n-1个元素有效,如何用该方法来打乱n个元素的次序。可以先将前n-1个元素打乱,
	  然后从`0~n中随机选择一个数k,调换牌[n]和牌[k]

关键:
1	  递归的方式就是:假设shuffle()对n-1个元素有效,如何用该方法来打乱n个元素的次序。可以先将前n-1个元素打乱,
	  然后从`0~n中随机选择一个数k,调换牌[n]和牌[k]
vector<int> shuffle(vector<int>& cards ,  int n)
{
	//对第0张牌,只剩一张,无法进行洗牌,返回
	if( 0 == n)
	{
		return cards;
	}
	//打乱前n-1张牌
	shuffle(cards , n-1);
	int k = randMinMax(0 , n);//随机挑选索引交换
	int temp = cards.at(k);
	cards.at(k) = cards.at(n);
	cards.at(n) = temp;
	return cards;
}
*/

int randMinMax(int min ,int max)
{
	if(min > max)
	{

		stringstream stream;
		stream << "min:" << min << ",max:" << max << " is wrong! min must less than max";
		throw(stream.str());
	}
	return (rand() % (max - min + 1) + min);

}

vector<int> shuffle(vector<int>& cards ,  int n)
{
	//对第0张牌,只剩一张,无法进行洗牌,返回
	if( 0 == n)
	{
		return cards;
	}
	//打乱前n-1张牌
	shuffle(cards , n-1);
	int k = randMinMax(0 , n);//随机挑选索引交换
	int temp = cards.at(k);
	cards.at(k) = cards.at(n);
	cards.at(n) = temp;
	return cards;
}

void process()
{
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值