看。。。很多算法问题都能找到它的现实原型

  

  昨晚在家看 “南洋十大邪术”,又发现徐锦江了,果然是在情色片中起家的,起兴处。。。被以前学校的一个小师弟抖屏搅了。。。悲剧!

由于金三银四的好时期,小师弟也跑去找工作了,也就碰到了各种各样的面试题,然后也就引出了今天的这篇博文,就是:如何产生1-100

之间的100个不重复的随机数,不过这里还好,在携程面试.net是没有笔试的:-)

 

     如果这是你是第一次看到这个题目,也许你的想法有很多。

 

1:首先从原始数组中随机选择一个数字,然后将该数字从数组中剔除,再随记选,再剔除,重复99次,就解决了。

    我们知道从数组中剔除一个元素的复杂度为O(N),那么随机选取n个数字,它的复杂度就是O(N2)了。

 

2:用hash作为中间过滤层,因为在数组中,我们采用随机数的话,也许随机数在多次随机中可能会有重复,所以需要用hash来判断一下,

    如果在hash中重复,则继续产生随机数,直到不重复为止,当然这个复杂度就不好说了,得要看随机数随机不随机了,好的话,O(N)搞定,

    不走运的话无上限~

 

3:就像标题说的一样,很多问题我们都能在现实生活中找到写照,毕竟很多东西是来源于现实,又抽象于现实,比如这个题目在现实生活中,

  可以对应到的就是“洗扑克牌”,在算法中也叫“洗牌原理”,我们知道洗扑克牌的方式就是随机的交换扑克牌的位置,又叫做"切牌",当你切了

   很多次后,我们的扑克牌就可以认为是足够乱了,复杂度也就变成了O(N),用代码实现就是这样的。

   <1> 先有序的生成52张牌,然后有序的放到数组中。

   <2>从1-52中随机的产生一个数,然后将当前次数的位置跟随机数的位置进行交换,重复52次,我们的牌就可以认为足够乱了。

 

4:代码实现

<1> 首先定义牌的数据结构,定义一个“花色”和“数字”

1         /// <summary>

2         /// 具体扑克牌

3         /// </summary>

4         public class Card

5         {

6             public char suit;

7 

8             public string num;

9         }

 

<2>有序的生成52张牌

 1         /// <summary>

 2         /// 开牌

 3         /// </summary>

 4         public void NewCard()

 5         {

 6             for (int i = 1; i <= card.Length; i++)

 7             {

 8                 var suit = ((i - 1) / 13) + 3;

 9                 var num = i % 13;

10 

11                 string temp;

12 

13                 switch (num)

14                 {

15                     case 1: temp = "A"; break;

16                     case 11: temp = "J"; break;

17                     case 12: temp = "Q"; break;

18                     case 0: temp = "K"; break;

19                     default: temp = num.ToString(); break;

20                 }

21 

22                 card[i - 1] = new Card()

23                 {

24                     suit = (char)suit,

25                     num = temp

26                 };

27             }

28         }

 

<3> 然后就是切牌了,刚才也说了思路,就是拿随机数的位置与当前i的位置进行交换,不过一说到交换就想起了“冒泡排序”,可能被毒害太

  深了(┬_┬),不知道你感觉到了没。

 1         /// <summary>

 2         /// 洗牌

 3         /// </summary>

 4         public void Shuffle()

 5         {

 6             for (int i = 0; i < card.Length; i++)

 7             {

 8                 var rand = new Random((int)DateTime.Now.Ticks).Next(0, card.Length);

 9 

10                 //因为随机数是伪随记,正真的随机数是要跟硬件打交道的,所以这里设置了停留1ms

11                 System.Threading.Thread.Sleep(1);

12 

13                 var temp = card[rand];

14 

15                 card[rand] = card[i];

16 

17                 card[i] = temp;

18             }

19         }

<4> 最后我们看看效果

看。。。很多算法问题都能找到它的现实原型
  1 using System;

  2 using System.Collections.Generic;

  3 using System.Linq;

  4 using System.Text;

  5 using System.Threading.Tasks;

  6 

  7 namespace ConsoleApplication1

  8 {

  9     public class Program

 10     {

 11         static void Main(string[] args)

 12         {

 13             CardClass cc = new CardClass();

 14 

 15             cc.NewCard();

 16 

 17             Console.WriteLine("\n\n=======================洗牌之前  ===========================\n");

 18             cc.Output();

 19 

 20             Console.WriteLine("\n\n=======================洗牌之后  ===========================\n");

 21             cc.Shuffle();

 22             cc.Output();

 23 

 24 

 25             Console.Read();

 26         }

 27     }

 28 

 29     public class CardClass

 30     {

 31         public Card[] card = new Card[52];

 32 

 33         /// <summary>

 34         /// 具体扑克牌

 35         /// </summary>

 36         public class Card

 37         {

 38             public char suit;

 39 

 40             public string num;

 41         }

 42 

 43         /// <summary>

 44         /// 开牌

 45         /// </summary>

 46         public void NewCard()

 47         {

 48             for (int i = 1; i <= card.Length; i++)

 49             {

 50                 var suit = ((i - 1) / 13) + 3;

 51                 var num = i % 13;

 52 

 53                 string temp;

 54 

 55                 switch (num)

 56                 {

 57                     case 1: temp = "A"; break;

 58                     case 11: temp = "J"; break;

 59                     case 12: temp = "Q"; break;

 60                     case 0: temp = "K"; break;

 61                     default: temp = num.ToString(); break;

 62                 }

 63 

 64                 card[i - 1] = new Card()

 65                 {

 66                     suit = (char)suit,

 67                     num = temp

 68                 };

 69             }

 70         }

 71 

 72         /// <summary>

 73         /// 洗牌

 74         /// </summary>

 75         public void Shuffle()

 76         {

 77             for (int i = 0; i < card.Length; i++)

 78             {

 79                 var rand = new Random((int)DateTime.Now.Ticks).Next(0, card.Length);

 80 

 81                 //因为随机数是伪随记,正真的随机数是要跟硬件打交道的,所以这里设置了停留1ms

 82                 System.Threading.Thread.Sleep(1);

 83 

 84                 var temp = card[rand];

 85 

 86                 card[rand] = card[i];

 87 

 88                 card[i] = temp;

 89             }

 90         }

 91 

 92         /// <summary>

 93         /// 输入牌型

 94         /// </summary>

 95         public void Output()

 96         {

 97             for (int i = 0; i < card.Length; i++)

 98             {

 99                 if (i % 13 == 0)

100                     Console.WriteLine();

101 

102                 Console.Write("{0}{1} ", card[i].suit, card[i].num);

103             }

104         }

105     }

106 }
View Code

看。。。很多算法问题都能找到它的现实原型

 

其实“洗牌原理”只要说破了是很简单的,就是你想不到,哈哈。。。然后小师弟也就明白了,我也就继续看徐锦江的精彩表现了,o(∩_∩)o 

 

你可能感兴趣的:(算法)