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

  

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

由于金三银四的好时期,小师弟也跑去找工作了,也就碰到了各种各样的面试题,然后也就引出了今天的这篇博文,就是:如何产生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> 首先定义牌的数据结构,定义一个“花色”和“数字”

/// <summary>
        /// 具体扑克牌
        /// </summary>
        public class Card
        {
            public char suit;

            public string num;
        }

 

<2>有序的生成52张牌

/// <summary>
        /// 开牌
        /// </summary>
        public void NewCard()
        {
            for (int i = 1; i <= card.Length; i++)
            {
                var suit = ((i - 1) / 13) + 3;
                var num = i % 13;

                string temp;

                switch (num)
                {
                    case 1: temp = "A"; break;
                    case 11: temp = "J"; break;
                    case 12: temp = "Q"; break;
                    case 0: temp = "K"; break;
                    default: temp = num.ToString(); break;
                }

                card[i - 1] = new Card()
                {
                    suit = (char)suit,
                    num = temp
                };
            }
        }

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

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

/// <summary>
        /// 洗牌
        /// </summary>
        public void Shuffle()
        {
            for (int i = 0; i < card.Length; i++)
            {
                var rand = new Random((int)DateTime.Now.Ticks).Next(0, card.Length);

                //因为随机数是伪随记,正真的随机数是要跟硬件打交道的,所以这里设置了停留1ms
                System.Threading.Thread.Sleep(1);

                var temp = card[rand];

                card[rand] = card[i];

                card[i] = temp;
            }
        }

<4> 最后我们看看效果

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main(string[] args)
        {
            CardClass cc = new CardClass();

            cc.NewCard();

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

            Console.WriteLine("\n\n=======================洗牌之后  ===========================\n");
            cc.Shuffle();
            cc.Output();

            Console.Read();
        }
    }

    public class CardClass
    {
        public Card[] card = new Card[52];

        /// <summary>
        /// 具体扑克牌
        /// </summary>
        public class Card
        {
            public char suit;

            public string num;
        }

        /// <summary>
        /// 开牌
        /// </summary>
        public void NewCard()
        {
            for (int i = 1; i <= card.Length; i++)
            {
                var suit = ((i - 1) / 13) + 3;
                var num = i % 13;

                string temp;

                switch (num)
                {
                    case 1: temp = "A"; break;
                    case 11: temp = "J"; break;
                    case 12: temp = "Q"; break;
                    case 0: temp = "K"; break;
                    default: temp = num.ToString(); break;
                }

                card[i - 1] = new Card()
                {
                    suit = (char)suit,
                    num = temp
                };
            }
        }

        /// <summary>
        /// 洗牌
        /// </summary>
        public void Shuffle()
        {
            for (int i = 0; i < card.Length; i++)
            {
                var rand = new Random((int)DateTime.Now.Ticks).Next(0, card.Length);

                //因为随机数是伪随记,正真的随机数是要跟硬件打交道的,所以这里设置了停留1ms
                System.Threading.Thread.Sleep(1);

                var temp = card[rand];

                card[rand] = card[i];

                card[i] = temp;
            }
        }

        /// <summary>
        /// 输入牌型
        /// </summary>
        public void Output()
        {
            for (int i = 0; i < card.Length; i++)
            {
                if (i % 13 == 0)
                    Console.WriteLine();

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

 

时间: 2025-01-18 21:39:59

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

登录事件时候-=号附近有语法错误 看来看去都没找到

问题描述 =号附近有语法错误 看来看去都没找到 private void button1_Click(object sender, EventArgs e) { string sql = "select * from T_USER where users='" + tb_user.Text + "'"; DataSet ds = account.Getdateset(sql); if (ds != null && ds.Tables[0].Rows.

=号附近有语法错误 看来看去都没找到 sql语句没错误呀

问题描述 =号附近有语法错误 看来看去都没找到 sql语句没错误呀 private void button1_Click(object sender, EventArgs e) { string sql = "select count(*) from T_USER where users='" + tb_user.Text.Trim() + "'"; DataSet ds = account.Getdateset(sql); if (ds != null &

很多时候我们都是缺少一个好的切入点(转)

  开发人员经常会碰到老板或上头安排的项目或需求,是自己完全陌生的领域,这个时候就会非常头痛,搜索引擎能解决大部分这些方面的问题,而有时因为自身问题或干脆找不到解决方案而非常抓狂......虽然干开发有10来年了,但还是会不时碰到这种问题,现做一下总结   前段时间老板出了一个难题给我,具体要求如下: 服务器上面有两张网卡分别连接电信和联通网络,要求软件在接到A请求时,使用电信网卡访问网络,接到B请求时,使用联通网卡访问网络,必须能多线程处理请求.还给了提示,说他听他朋友讲,使用路由功能就可以简

很多的社会生活都可以分为前台和后台

真是不好意思,开头得先把社会学学者戈夫曼搬出来了,按这位前辈的社会互动理论,很多的社会生活都可以分为前台和后台,就我理解也就是"人前一套"与"人后一套"的区别.窃以为,这套说法在社交网络上同样适用,10年来主宰社交网络的一直是Facebook(2004年).LinkedIn(2002年)等实名网站,它们大概围绕扎克伯格所倡导的"开放"与"身份的一致性"在转,它们也主要是记录了我们的人前种种. 但很显然,微信类产品.SnapCh

c语言-C语言寻找矩阵鞍点问题麻烦看看我的算法哪里有问题

问题描述 C语言寻找矩阵鞍点问题麻烦看看我的算法哪里有问题 我写了个算法,但是不知道为什么运行不出结果. 麻烦看看我的算法错在了哪里(请不要更换我的算法). 解决方案 /*寻找行里面最大的值所在列,找到后再看该元素是不是所在列的最小值,如果是则找到,否则下一行接着找,弱到最后一行都没有则没有鞍点*/ for(i = 0; i < n; i++) { max = a[i][0]; //记录行里面的最大值 column = 0; //记录行最大值所在列号 //找行最大值的列号 for(j = 1;

时间管理这事对很多人来说都是难事

"我拖延-到最后一刻才拼命把事情做完." "有时候我会把一天的事情塞得太满而倍感压力--" 上面说的是你吗? 时间管理这事对很多人来说都是难事,特别在这个注意力不容易集中容易频繁切换屏幕和工作任务的今天,再好的GTD产品好像都不能满足我们了.当时间管理这事成了很多人膝盖上的伤,一款叫Timeful的智能时间管家可能有机会出来治疗一下.这产品还没推出,却已经拿了700万美元的A轮融资,投资机构包括了Khosla Ventures.KPCB等. 这个卖关子的app到底是

c语言-求大神来看看我的算法有没有可行性,最好能给点建议

问题描述 求大神来看看我的算法有没有可行性,最好能给点建议 读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字. 输入格式:每个测试输入包含1个测试用例,即给出自然数n的值.这里保证n小于10^100. 输出格式:在一行内输出n的各位数字之和的每一位,拼音数字间有1 空格,但一行中最后一个拼音数字后没有空格. 输入样例: 1234567890987654321123456789 输出样例:yi san w 我的代码如下: #include<stdio.h> #include&l

想捐钱给谁在这个网上都能找到

前线:想捐钱给谁?在这个网上都能找到! 林伟贤/文 想捐钱,却找不到让你兴奋的慈善项目?今天和大家分享"全球捐赠网"的商业模式.数百个慈善项目在这里注册,等你捐助.七年前,丹尼斯辞去世界银行的工作,创办这个互联网平台,至今已帮助数万名捐助者把1000多万美元捐给一千多个项目.这个创意是不是很棒? 全球捐赠网(Global Giving)的建立,使捐款者和受捐者的需求在互联网平台上实现对接. 想获得捐款的人可以上传自己的捐款申请,经审批合格后就可以将自己的信息挂在网上.网站会按照所在地区

很多媒体人都在苦逼哈哈的搞年终盘点,或悲情或煽情或激情

2013年就要过去了,我很怀念它.一般这个时间,很多媒体人都在苦逼哈哈的搞年终盘点,或悲情或煽情或激情.而我在一日三省吾身(日,名词,含义同"天")之后,突然惊讶的发现自己居然没有用"互联网思维"一词写过稿子,这对于我这样自诩为游走在北京昌平区天通苑共和国城乡结合部的先锋写手来说,是一件多么落伍掉粉的事情. 我的脑海里仿佛有黑白两个小人正在做激烈的斗争,这俩小人从我上小学就开始斗争了.那时,小白人说:"我去买袋一毛钱的酸梅粉吧!"小黑人义正言辞的