zoukankan      html  css  js  c++  java
  • 看。。。很多算法问题都能找到它的现实原型

      

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

    由于金三银四的好时期,小师弟也跑去找工作了,也就碰到了各种各样的面试题,然后也就引出了今天的这篇博文,就是:如何产生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("
    
    =======================洗牌之前  ===========================
    ");
     18             cc.Output();
     19 
     20             Console.WriteLine("
    
    =======================洗牌之后  ===========================
    ");
     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 

  • 相关阅读:
    输出控制符的详解
    printf函数的讲解
    关于字节、Ascll码、字符的存储的讲解
    1.2
    1.1
    OS模块学习笔记
    time时间模块总结
    编译py为exe
    python计算excel平均值和标准差
    Python与Excel交互--Xlwings
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/3604198.html
Copyright © 2011-2022 走看看