标签:style blog http color os io java ar for
如何产生1-100之间的100个不重复的随机数
如果这是你是第一次看到这个题目,也许你的想法有很多。
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];