A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© guo329838627 中级黑马   /  2013-9-13 17:39  /  2284 人查看  /  17 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 guo329838627 于 2013-9-21 10:48 编辑

            要求 产生54个随机数,随机数范围(1-54),然后将其放到一个新的数组中,数字不能重复,也就是把1-54之间的数打乱,然后放到数组中。
             求解!!!

17 个回复

倒序浏览
本帖最后由 §風過無痕§ 于 2013-9-13 19:00 编辑

有木有搞错  随机数范围(1-54) 要求 产生54个随机数且不重复  而随机数的性质是包括下限而不包括上限    大神也难做  
   。。。。。。。。。
  • using System.Collections;


    namespace 不重复随机数
    {
             class Program
            {
                   static void Main(string[] args)
                   {
                        Hashtable hashtable = new Hashtable();//使用默认的初始化容器来初始化Hashtable类的新的空实例
                        Random rdm = new Random();//初始化Random类的新实例
                        int count = 0;//记录输出的个数
                        for (int i = 0; hashtable.Count < 54; i++)//遍历hashtable中的Key
                       {
                                int nValue = rdm.Next(1, 54);//定义变量nValue用于存储产生的随机数
                                if (!hashtable.ContainsValue(nValue))//判断相应键/值是否存在
                                {
                                          hashtable.Add(nValue, nValue);
                                          count++;//记录个数数目 纯粹个人调试用 没任何意义
                                          Console.Write(nValue.ToString() + ",第{0}个\n", count);

                                  }

                       }
                       Console.ReadKey();
                 }
           }
    }
初次使用Hashtable 有不对的地方 请多多指教!


回复 使用道具 举报
  1. int[] num=new int[54];//声明一个int数组容量54
  2.             int index = 0;//随即数
  3.             int tep = 0;
  4.             //先给数组赋值,1-54
  5.             for(int i =0;i<54;i++)
  6.             {
  7.                 num[i]=i+1;
  8.             }
  9.             Random r = new Random();
  10.             //打乱排序并交换位置
  11.             for (int i = 0; i < num.Length; i++)
  12.             {
  13.                 index= r.Next(i, 54 - 1);
  14.                 tep = num[i];
  15.                 num[i] = num[index];
  16.                 num[index] = tep;
  17.             }
  18.             foreach (int i in num)
  19.             {
  20.                 Console.WriteLine(i);
  21.             }
  22.             Console.ReadKey();
复制代码
这是我的思路,希望对你有帮助。
回复 使用道具 举报
说下我的想法,主要问题就是要求不重复。大体思路就是这样,先制造一个长度为54的数组a,从a[0]-a[53]分别对应1-54,在定义一个长度为54的数组b存储结果。
1、生成一个0-53的随机数i,然后让b[0]=a[i]
2、删除a数组中下标为i的这个元素,让a数组等于这个新的数组。不知道有没有这样的函数,没有的话自己写一个,比较简单,思路就是新数组中,下标小于i的不变,下标大于等于i的去对应旧数组中的下一个元素。
3、生成一个0-52的随机数i,然后让b[1]=a[i]
4、删除a数组中下标为i的这个元素,让a数组等于这个新的数组。
5、生成一个0-51的随机数i,然后让b[2]=a[i]
6、删除a数组中下标为i的这个元素,让a数组等于这个新的数组。
.
.
.
.//就是2个步骤一个for循环
循环进行53次就行(这一次是生成一个0-1的随机数,然后把a数组中对应的数(此时a数组就2个数了)放入b[52])。
最后一步就是将a[0](a数组中最后剩下的那个数)赋给b[53]

思路就是这样,代码我得好好想想,貌似还没弄过这样的题


回复 使用道具 举报
其实有点小bug
应该是r.next(i,54)的
回复 使用道具 举报
数组  哈希表   集合 都能解决!  ArrayList  list=new ArrayList();   list 中有一个方法用于判断集合中是否已存在即将添加的值
回复 使用道具 举报
yueyp 中级黑马 2013-9-13 20:35:16
7#
  static void Main(string[] args)
        {
            int i = 0;
            int[] num = new int[54]; //定义数组存放产生的随机数
            while (i < 54)
            {
                Random ran = new Random();
                int n = ran.Next(1, 55);  //从1-54之间产生一个随机数
                int j;
                for ( j = 0; j < i; j++)
                {
                    if (n == num[j])      //如果产生的随机数在数组中存在则要break 重新产生
                        break;
                }
                if (j == i)
                {
                    num[i] = n;           //把元素添加到数组中
                    i++;
                }
            }

            foreach (int item in num)
            {
                Console.WriteLine(item);  // 打印数组中的元素
            }

            Console.ReadKey();
        }
回复 使用道具 举报
七里香 发表于 2013-9-13 19:23
这是我的思路,希望对你有帮助。

挺独特的想法,思路上并不是关心每个生成的随机数是多少,而是通过获得的随机数来决定排序,不过你这里用index= r.Next(i, 54);意味着一个数字只能和下标大于等于它的数交换位置,是不是有失公平性啊,
这里我自行定义两个说法,主动换位和被动换位。
主动换位:num对应的数字进行的换位,只有当index=i的时候才不会进行换位,也就是说主动换位时,发生换位的几率是53/54,
被动换位:num[index]对应的数字进行的换位,它换位是由这次随机数字决定的,这个几率是1/54。

主动换位后依然有机会继续换位(包括主动和被动)
被动换位后就没机会换位了,因为你换到前面了,i已经不会再遍历到你了。

比如:54这个数字最多只有一次被动换位的机会(换位次数可能0或1),
53这个数字,有一次主动换位的机会,此次主动换位只能和最后一个数字换(可能已经不是54了,不过这不重要),所以换了之后程序就结束了。或者主动换位之前被动换位了。所以53这个数字换位次数(有且有0或1次)。
52这个数字可能换位次数为0次(轮到他主动换位的时候脸黑,没换上,之后又没有被被动换位),1次(主动和最后一个数字换位,或者被动换位一次)或者2次(主动和倒数第二个数字换位,再主动和最后一个数字换位。或者主动和最后一个数字换位,再被动换位一次)
51可能换位次数0、1、2或3次






1可能换位次数0、1、2、3、4..........或53次。
这里index= r.Next(i, 54);是不是改成index= r.Next(0, 54);比较好呢,这样增加了可进行被动换位的次数,而且虽然对于主动换位的次数,1仍然是最多的53次,54仍然是0次。但是对于任何一个数字,可能进行的最多换位次数(主动+被动)是相等的,都是54次。
但是主动和被动换位还是对概率(也就是随机性)有影响的,毕竟所谓主动换位就是必然进行的换位,而被动换位是看运气的换位。拿1和54这两个数字来说,只有当第一次index=0的时候,1才没有进行这次主动换位(这个几率是1/54),其余时刻1都会更换位置的,而且1更换的位置只要不是最后一个,1依然有主动换位的机会。对于54这个数字,每次只能等待着被动换位,所以即使这种情况下,1这个数字换位次数的数学期望远远也要高于54这个数字换位的数学期望。
感觉随机性不是很强的说。
回复 使用道具 举报 1 0
大虾挂了 发表于 2013-9-13 20:46
挺独特的想法,思路上并不是关心每个生成的随机数是多少,而是通过获得的随机数来决定排序,不过你这里用 ...

上面最后一段打错了,主动换位是53/54几率进行的换位
回复 使用道具 举报
§風過無痕§ 发表于 2013-9-13 18:01
有木有搞错  随机数范围(1-54) 要求 产生54个随机数且不重复  而随机数的性质是包括下限而不包括上限     ...

小小的说下我的想法,感觉这样运行效率比较低,毕竟人家只要54个随机数,而你这里除非神RP,否则进行的循环次数要比54大很多的。
期望上你这里的循环次数应该=54*(1/54+1/53+1/52+1/51+1/50+。。。。。。+1/1),这是调和级数,项数很小的时候只能一项一项加,我就加了后10项,大概162,算上前面的40项肯定还会大不少。
应该找个优化的方法。
回复 使用道具 举报
大虾挂了 发表于 2013-9-13 21:05
小小的说下我的想法,感觉这样运行效率比较低,毕竟人家只要54个随机数,而你这里除非神RP,否则进行的循 ...

嗯,不错只要加一个判定就ok了。
亲你是学数学专业的吗?这么厉害。
回复 使用道具 举报
以下基于我4楼写的方法的代码,由于数组没有删除某个元素的函数,自己可以去编写,但是无法改变数组长度(虽然这个对这道题没影响)。我采用了自己不太了解的集合,.remove(),可以删除集合中的元素,不过是对其中元素的操作,不是对下标的操作,所以括号中写的是start[index]。
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;

  5. namespace 生成54个随机数_要求从1_54不重复
  6. {
  7.     class Program
  8.     {
  9.         static void Main(string[] args)
  10.         {
  11.             int index;
  12.             List<int> start = new List<int>(); //存储初始数据
  13.             List<int> result = new List<int>(); //存储结果数据

  14.             for (int i = 0; i < 54; i++)
  15.                 start.Add(i + 1);


  16.             Random r = new Random();  //定义一个随机数

  17.             //54次循环,每次循环确定一个数
  18.             for (int i = 0; i < 54; i++)
  19.             {
  20.                 index = r.Next(0, 54 - i); //每次循环,随到的数字都会被从start集合中删除,所以每次循环集合长度少1,下标取值范围-1
  21.                 result.Add(start[index]); //将随到的数字放入result集合中
  22.                 start.Remove(start[index]); //防止数据重复,删除被随机到的数据
  23.             }
  24.             foreach (int i in result)
  25.                 Console.Write("{0}\t", i);
  26.                 Console.ReadKey();

  27.         }
  28.     }
  29. }
复制代码
回复 使用道具 举报
七里香 发表于 2013-9-13 21:16
嗯,不错只要加一个判定就ok了。
亲你是学数学专业的吗?这么厉害。

不是数学专业的,只不过数学学的一直还不错,吹吹自己风光的历史吧,高考数学我是满分滴,但是大学就坑爹了,根本没学,高数好像差点挂科,不过后来重新认真学过一段时间高数。
回复 使用道具 举报
本帖最后由 蒋元龙 于 2013-9-13 22:09 编辑
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;

  6. namespace ConsoleApplication5
  7. {
  8.     class Program
  9.     {
  10.         static void Main(string[] args)
  11.         {

  12.             Rand();
  13.             Console.ReadKey();
  14.         }

  15.         public static void Rand()
  16.         {
  17.             ArrayList arand = new ArrayList();//用来存储随机数
  18.             Random rand = new Random();
  19.             for (int i = 0; i < 54; i++)
  20.             {
  21.                 int rd = rand.Next(1, 55);//产生一个1-54随机数给rd,Next()里面的最大值是不会产生的,跟数组下标一样
  22.                 if (arand.Contains(rd))
  23.                 {
  24.                     i--; //如果数组中存储这个随机数,重新生成一个随机,i来控制随机数个数
  25.                     continue;
  26.                 }
  27.                 else
  28.                 {
  29.                     arand.Add(rd);
  30.                 }
  31.               
  32.             }
  33.             foreach(int d in arand)
  34.                 Console.Write("{0}\t",d);
  35.         }
  36.     }

  37. }
复制代码
回复 使用道具 举报
     //思路很简单啊,循环让计算机做
            Random random = new Random();
            int[] number = new int[54];
            int count = 1;
            bool flag;
            number[0] = random.Next(1, 54);//赋值数组第一个数
            
          //得到一个随机数如果和之前的不同就赋给第2个数,直到赋满54个数
            while (count < 54)
            {
                flag = true;
                int temp = random.Next(1, 54);
                for (int j = 0; j < count; j++)
                {
                    if (number[j] == temp)
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag == true)
                {
                    number[count] = temp;
                    count++;
                }
            }
回复 使用道具 举报
产生一个数组1-54 然后random它的下标 放进新数组  快给技术分!
回复 使用道具 举报
王赟 发表于 2013-9-14 13:42
产生一个数组1-54 然后random它的下标 放进新数组  快给技术分!

??
回复 使用道具 举报
我的想法是,循环体(不断产生随机数,并且赋值给一个变量,  判断if(如果这个变量的数字等于产生的随机数,那么则重新产生),然后把产生的数字赋给数组)。最后打印输出,不过这个方法的缺点是效率很低
贴出我的代码
  1. int[] resultNum = new int[54]; //用于存储随机数的数组
  2. int temp = 0;
  3. Random random = new Random();
  4. bool repeat = false;
  5. for (int i = 0; i < 54; i++)
  6. {
  7. repeat = true;
  8. while (repeat)
  9. {
  10. repeat = false;
  11. temp = random.Next(1, 55); //产生1-54的随机数,并赋值给temp
  12. for (int j = 0; j < i; j++)
  13. {
  14. if (temp == resultNum[j]) //如果产生的随机数与数组中的某个数相同,则break,重新产生
  15. {
  16. repeat = true;
  17. break;
  18. }
  19. }
  20. }
  21. resultNum[i] = temp; //把随机数赋值给数组resultNum
  22. }
  23. for (int i = 0; i < 54; i++)
  24. Console.Write("{0}\t",resultNum[i]); //打印输出这些数
  25. Console.ReadKey();
  26. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马