除了前一篇的完美洗牌问题,还有一种洗牌,就是乱序(shuffle)的问题,将54张有序的扑克牌的顺序打乱,实现洗牌操作。

局部洗牌法

1。随机产生一个1-n的数x,做为第一张牌。
2。随机产生一个1-(n-1)的数y,如果y<x,则将y作为第二张牌,否则将y+1作为第二张牌。
3。随机产生一个1-(n-i)的数z,取第z个没有被抽出来的作为第i张牌。(i=3,4,5…54)
这种算法的复杂度为O(N^2),因为计算每个随机数的牌号平均要执行(N/2)次比较。
对应于现实中的扑克牌,这种算法等于每次从牌堆中随机抽一张,放到另一堆上,直到抽完为止,这里新的一堆就是洗完的牌序。

改进:

方法一由于计算随机数对应的牌号平均要执行(N/2)次比较,所以复杂度为O(N^2),N*N的第一个N是牌的数目,无法优化,但是第二个N是确定牌的序号,这个是否有办法优化呢?
第一种优化就是每次抽出一张牌后,就将之后的所有牌向前移动一个单位,下次产生的随机数就是目标牌的下标。
如第一次随机数为3,抽出3,扑克牌数组变为1 2 4 5 6 7…
第二次抽出6,直接取数组的第六个元素即7,然后把7之后的牌前移一个单位。这样牌的定位复杂度就是1了,但是移动的复杂度仍为N/2,所以这种算法并没有起到效率优化的目标。
第二种优化是为树状数组。用一个长为54的树状数组 used 存储 1-i 张牌中被投抽出来的牌的张数。这样 i-used[i] 就是牌号为 i 的扑克的序号。然后用2分查找的方式,就可以快速确定随机数对应的牌号,树状树的复杂度为logn,这样总的算法复杂度为O(NlogN)。
但是考虑到一种54张牌,树状数组优化带来的性能提升很小,比起程序代码带来的可维护性损失,颇不值得。

全局洗牌法


1。随机产生一个1-n的数x,然后让第x张牌和第1张牌互相调换。
2。随机产生一个1-n的数y,然后让第y张牌和第2张牌互相调换。
3。随机产生一个1-n的数z,然后让第z张牌和第i张牌互相调换。(i=3,4,5…54)
这种算法的复杂度为O(N)。
代码如下

void get_rand_number(int array[], int length)
{    int index;    int value;    int median;    if(NULL == array || 0 == length)    return ;    /* 每次发牌的时候任意分配待交换的数据 */    for(index = 0; index < length; index ++){    value = rand() % length;    median = array[index];    array[index] = array[value];    array[value] = median;    }
}

递归思想

我们有n张牌,不妨先假设有一个洗牌函数shuffle(….),能完美的洗出n-1张牌 。拿第n张牌来打乱前面n-1的洗牌顺序,从而得到n张牌的最终结果。

#include <iostream>
#include <cstdlib>
using namespace std;//随机指定区域内的数
int MyRand(int low, int high)
{return low + rand() % (high - low + 1);
}int* shuffle(int* cards, int n)
{if (n <= 0)return cards;shuffle(cards, n - 1);int rand = MyRand(0, n);int temp = cards[rand];cards[rand] = cards[n];cards[n] = temp;return cards;
}int main()
{for (int k = 1; k <= 10; k++){int cards[52] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,47, 48, 49, 50, 51, 52,};cout << endl;shuffle(cards, 52);//  洗牌for (int i = 1; i <= 52; i++){cout << cards[i - 1] << " ";if (i % 13 == 0)cout << endl;}}cout << endl;system("PAUSE");return 0;
}

参考网址

【1】洗牌算法 - hankjin的日志 - 网易博客
http://hankjin.blog.163.com/blog/static/3373193720109141128016/
【2】扑克牌洗牌算法 - CC专栏 - 博客频道 - CSDN.NET
http://blog.csdn.net/oktears/article/details/19435613?utm_source=tuicool&utm_medium=referral
【3】扑克牌的完美洗牌算法 - borey的个人空间 - 开源中国社区
http://my.oschina.net/xlplbo/blog/312231?fromerr=DLYCrycF

完美洗牌问题(打乱数组间各元素的顺序)相关推荐

  1. java 洗牌_java数组之完美洗牌算法

    题目详情 有个长度为2n的数组{a1,a2,a3,...,an,b1,b2,b3,...,bn},希望排序后{a1,b1,a2,b2,....,an,bn},请考虑有无时间复杂度o(n),空间复杂度0 ...

  2. java 完美洗牌,(2)数组相关算法题目

    数组是最简单的数据结构,占据连续内存并且按顺序存储. 以下是与数组有关的算法题目. (1)查询数组中重复数字 算法思路:(1)利用hash表,没有便放进去,有就返回(Java中HashMap存数字都是 ...

  3. 程序员编程艺术第三十四~三十五章:格子取数问题,完美洗牌算法

    第三十四~三十五章:格子取数,完美洗牌算法 作者:July.caopengcs.绿色夹克衫.致谢:西芹_new,陈利人, Peiyush Jain,白石,zinking. 时间:二零一三年八月二十三日 ...

  4. 程序员编程艺术第三十四 三十五章 格子取数问题,完美洗牌算法

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 第三十四 ...

  5. 完美洗牌问题——核心思想与代码

    完美洗牌问题系列文章: 提示:很重要的思想 1.完美洗牌问题--整体交换数组的左右2部分 2.完美洗牌问题--计算位置i下次要被挤到哪个位置j? 这2个文章,都是为本文做铺垫的,循序渐进理解什么是完美 ...

  6. 关于洗牌的研究(六)——从数学到魔术之完美洗牌

    爱学习,勤思考:学数学,玩魔术.欢迎点击头部蓝字关注MatheMagician,这里有你要的奇迹! 写再前面:本系列作品由MathMagician独家首发,一共有七篇,从数学和魔术两个角度对日常生活中 ...

  7. UVa Problem 10205 Stack ’em Up (完美洗牌术)

    // Stack 'em Up (完美洗牌术) // PC/UVa IDs: 110205/10205, Popularity: B, Success rate: average Level: 1 / ...

  8. php 108张牌洗牌,完美洗牌原理大揭秘 手把手图文教程!呕心沥血的超级干货...

    原标题:完美洗牌原理大揭秘 & 手把手图文教程!呕心沥血的超级干货 先感慨一下,昨晚写到半夜,今天又修改了很多遍,我终于把这篇文章写完了. 然后自夸一下,我敢保证,你从来没有看过像这样的完美洗 ...

  9. 洗牌算法java 剑指_扑克牌的完美洗牌算法

    思路: 递归思想.我们有n张牌,不妨先假设有一个洗牌函数shuffle(....),能完美的洗出n-1张牌 .拿第n张牌来打乱前面n-1的洗牌顺序,从而得到n张牌的最终结果. 代码如下: #inclu ...

最新文章

  1. 提升vector性能的几个技巧
  2. DCMTK:存储服务类提供者(C-STORE操作)
  3. MT6580热设计要求
  4. MYSQL的索引类型:PRIMARY, INDEX,UNIQUE,FULLTEXT,SPAIAL 有什么区别?各适用于什么场合?...
  5. 打CALL APP 项目进展 总体计划
  6. 离线语法设置 科大讯飞_科大讯飞智能键盘K710评测 输入速度超级加倍
  7. SQL Server 2008 R2 数据库安装
  8. 推流中转服务器,视频推流服务器EasyRTMPLive拉转推过程当中遇到复杂目的地址解决方法?...
  9. C++ 面向对象程序三大特性之 多态
  10. #leetcode刷题之路39-组合总和
  11. arduino控制点阵屏与蜂鸣器_还在为遥控项目发愁?Arduino遥控套装解决你的所有问题(下)...
  12. ajaxfileupload 监听上传进度_一篇文章学会文件上传
  13. 合力叉车3d模型_文章分享:《种植体颈部壁厚度和基台螺钉尺寸的生物力学评估:3D非线性有限元分析》...
  14. 项目管理需要具备什么能力?
  15. 35岁的程序员:第9章,女测试
  16. Firefox同步密钥丢失的解决办法
  17. Vue+高德地图API的使用(点击地图搜索周边信息)
  18. 浅谈 D-Bus、udevd 和 hald
  19. Received status code 502 from server: Bad Gateway
  20. 计算机毕设(附源码)JAVA-SSM基于微信平台的匿名电子投票系统

热门文章

  1. Linux文件系统类型
  2. Design Data-Intensive Applications 读书笔记三 查询语句
  3. chinapay java_Chinapay应用技术部Java编码规范.docx
  4. JS 删除对象和数组中的某个属性
  5. MPB:中科院深圳先进院戴磊组小鼠粪便样本中短链脂肪酸的定量检测
  6. CVE-2012-0003:Microsoft Windows Media Player winmm.dll MIDI 文件堆溢出漏洞调试分析
  7. 牛客网软通动力软件测试机试_软通动力测试工程师笔试题
  8. 【C语言】函数基础知识点总结
  9. netty 拆包和粘包 (三)
  10. laravel tcg/voyager 安装问题记录