算法-随机不重复数列生成

简介:

今天上班的时候网上看到题目很简单,题目是这样的:给定一个正整数n,需要输出一个长度为n的数组,数组元素是随机数,范围为0 – n-1,且元素不能重复。比如 n = 3 时,需要获取一个长度为3的数组,元素范围为0-2;简单的理解就是生成一个无序的随机数组,在路上想了一下回来用三种方式方式实现了一下;OC实现了一下,文章最末尾顺便有C#的是实现方法;

永远的While

while基本上学过语言的最开始的流程分支语句都会涉及到while,如果存在就一直随机,不存在就跳出判断,一般最开始想到都是这样方法:

1
2
3
4
5
6
7
8
9
10
11
12
+ ( NSArray  *)getResultOne:( NSInteger )count{
     NSMutableArray  *arr=[ NSMutableArray  array];
     for  ( NSInteger  i=0; i<count; i++) {
         NSInteger  number=arc4random()%count;
         //如果存在就一直随机下去
         while  ([arr containsObject:@(number)]) {
             number=arc4random()%count;
         }
         [arr addObject:@(number)];
     }
     return  arr;
}

 调用方式:

1
2
3
4
5
NSArray  *arr= nil ;
arr=[ArrayRandom getResultOne:5];
for  ( NSInteger  i=0; i<[arr count]; i++) {
     NSLog (@ "%@" ,[arr[i]stringValue]);
}

数组筛选

第二种方式其实说起来写代码叶遇到过这种情况,有点类似于从箱子中取球,放回去和不回去的这种模式,如果箱子中的每个球颜色都不一样就是取出来就不放回去,那么取的下一个一定和之前的颜色不一样,具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+ ( NSArray  *)getResultTwo:( NSInteger )count{
     NSMutableArray  *originalArr=[ NSMutableArray  array];
     NSMutableArray  *resultArr=[ NSMutableArray  array];
     //按照顺序生成一个数组
     for  ( NSInteger  i=0; i<count; i++) {
         [originalArr addObject:@(i)];
     }
     NSInteger  total=count;
     for  ( NSInteger  i=0; i<count; i++) {
         NSInteger  index=arc4random()%total;
         //随机出来的结果添加到结果集
         [resultArr addObject:originalArr[index]];
         //删除原始数组中的结果
         [originalArr removeObject:originalArr[index]];
         total--;
     }
     return  resultArr;
} 

交换法

交换法的意思就是需要先初始化一个数组,随机生成索引,每次随机出来索引位置的值都放在头部或者尾部,然后下次取索引的时候就不去头部和尾部的索引,举一个简单的例子,假设初始化的数组是3,8,6,9,随机出来的索引范围是0-3,假设第一随机随机的时2,头部交换就是将3和6换一个位置,6,8,3,9,下一次取的索引范围是1-3,尾部交换也是类似,C#版本中是头部交换,OC是尾部交换,原理是一样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+( NSArray  *)getResultThird:( NSInteger )count{
     NSMutableArray  *originalArr=[ NSMutableArray  array];
     NSMutableArray  *resultArr=[ NSMutableArray  array];
     //按照顺序生成一个数组
     for  ( NSInteger  i=0; i<count; i++) {
         [originalArr addObject:@(i)];
     }
     NSInteger  maxIndex=count-1;
     for  ( NSInteger  i=0; i<count; i++) {
         NSInteger  index=arc4random()%(maxIndex+1);
         [resultArr addObject:originalArr[index]];
         //将随机生成的数字赋值给最末位
         originalArr[index]=originalArr[maxIndex];
         //控制最大索引的值
         maxIndex--;
     }
     return  resultArr;
}

 这时我第一次写的时候用的代码,细心的可能发现定义了两个数组,其实没有必要,一个就够,下面的是改进代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
+( NSArray  *)getResultFour:( NSInteger )count{
     NSMutableArray  *resultArr=[ NSMutableArray  array];
     //按照顺序生成一个数组
     for  ( NSInteger  i=0; i<count; i++) {
         [resultArr addObject:@(i)];
     }
     NSInteger  maxIndex=count-1;
     for  ( NSInteger  i=0; i<count; i++) {
         NSInteger  index=arc4random()%(maxIndex+1);
         //随机的值和末位进行互换
         NSString   *temp=resultArr[index];
         resultArr[index]=resultArr[maxIndex];
         resultArr[maxIndex]=temp;
         //控制最大索引的值
         maxIndex--;
     }
     return  resultArr;
}

 调用方式同之前的一样:

1
2
3
4
5
6
7
8
9
10
11
NSArray  *arr= nil ;
   arr=[ArrayRandom getResultThird:5];
   for  ( NSInteger  i=0; i<[arr count]; i++) {
       NSLog (@ "%@" ,[arr[i]stringValue]);
   }
   
   NSArray  *arr= nil ;
   arr=[ArrayRandom getResultFour:5];
   for  ( NSInteger  i=0; i<[arr count]; i++) {
       NSLog (@ "%@" ,[arr[i]stringValue]);
   }

 C#版本代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class  Program
     {
         static  void  Main( string [] args)
         {
             //初始化一个数组,如果数组没有赋值,默认是0
             //int[] arr = SolveProblemWayOne(5);
             //int[] arr = SolveProblemWaySecond(5);
             //int[] arr = SolveProblemWayThird(10);
             int [] arr = SolveProblemWayFour(5);
             for  ( int  i = 0; i < arr.Length; i++)
             {
                 Console.Write(arr[i].ToString());
             }
             Console.ReadKey();
         }
         /// <summary>
         /// 循环判断随机出来的数字是否在数组中
         /// </summary>
         /// <param name="total"></param>
         /// <returns></returns>
         public  static  int [] SolveProblemWayOne( int  count)
         {
             List< int > resultList =  new  List< int >();
             Random random =  new  Random();
             for  ( int  i = 0; i < count; i++)
             {
                 int  number = random.Next(1, count + 1);
                 while  (resultList.Contains(number))
                 {
                     number = random.Next(1, count + 1);
                 }
                 resultList.Add(number);
             }
             return  resultList.ToArray();
         }
         /// <summary>
         /// 按照顺序生成一个数组
         /// </summary>
         /// <param name="total"></param>
         /// <returns></returns>
         public  static  int [] SolveProblemWaySecond( int  count)
         {
             List< int > orignalList =  new  List< int >();
             List< int > resultList =  new  List< int >();
             for  ( int  i = 0; i < count; i++)
             {
                 orignalList.Add(i);
             }
             int  maxIndex = count;
             Random random =  new  Random();
             for  ( int  i = 0; i < count; i++)
             {
                 //随机索引
                 int  index = random.Next(0, maxIndex);
                 resultList.Add(orignalList[index]);
                 orignalList.RemoveAt(index);
                 maxIndex--;
             }
             return  resultList.ToArray();
         }
         /// <summary>
         /// 不删除数据,然后的问题就是给最后的东西赋值
         /// </summary>
         /// <param name="count"></param>
         /// <returns></returns>
         public  static  int [] SolveProblemWayThird( int  count)
         {
             List< int > orignalList =  new  List< int >();
             List< int > resultList =  new  List< int >();
             for  ( int  i = 0; i < count; i++)
             {
                 orignalList.Add(i);
             }
             int  minIndex =0;
             Random random =  new  Random();
             for  ( int  i = 0; i < count; i++)
             {
                 //随机索引
                 int  index = random.Next(minIndex, count);
                 resultList.Add(orignalList[index]);
                 //交换,由于索引自减,不需要将随机的值赋值到最后
                 //int temp = orignalList[index];
                 orignalList[index] = orignalList[minIndex];
                 //orignalList[minIndex] = temp;
                 minIndex++;
             }
             return  resultList.ToArray();
         }
 
 
         /// <summary>
         /// 简洁方式
         /// </summary>
         /// <param name="count"></param>
         /// <returns></returns>
         public  static  int [] SolveProblemWayFour( int  count)
         {
             List< int > resultList =  new  List< int >();
             for  ( int  i = 0; i < count; i++)
             {
                 resultList.Add(i);
             }
             int  minIndex=0;
             Random random =  new  Random();
             for  ( int  i = 0; i < count; i++)
             {
                 //随机索引
                 int  index = random.Next(minIndex, count);
                 //头部交换
                 int  temp = resultList[index];
                 resultList[index]=resultList[minIndex];
                 resultList[minIndex] = temp;
                 minIndex++;
             }
             return  resultList.ToArray();
         }
  
  
     }
}
  
本文转自Fly_Elephant博客园博客,原文链接:http://www.cnblogs.com/xiaofeixiang/p/4234223.html,如需转载请自行联系原作者
相关文章
|
6月前
|
算法
【算法优选】 动态规划之斐波那契数列模型
【算法优选】 动态规划之斐波那契数列模型
|
6月前
|
机器学习/深度学习 算法 测试技术
【动态规划】C++算法:446等差数列划分 II - 子序列
【动态规划】C++算法:446等差数列划分 II - 子序列
|
3月前
|
存储 算法
读《趣学算法》:重开算法之门,神奇的兔子数列(斐波那契数列)
本文通过《趣学算法》中的斐波那契数列问题,探讨了算法的递归实现、时间复杂度分析,并展示了如何通过迭代和优化存储空间来改进算法,最终将时间复杂度从指数级降低到线性级,并将空间复杂度从线性级降低到常数级。
87 0
读《趣学算法》:重开算法之门,神奇的兔子数列(斐波那契数列)
|
5月前
|
算法
算法特训,AB5 .点击消除BC.149简写单词牛客.除2!牛客.Fibonacci数列
算法特训,AB5 .点击消除BC.149简写单词牛客.除2!牛客.Fibonacci数列
|
6月前
|
算法
算法沉淀 —— 动态规划篇(斐波那契数列模型)
算法沉淀 —— 动态规划篇(斐波那契数列模型)
56 0
|
6月前
|
算法
算法修炼-动态规划之斐波那契数列模型
算法修炼-动态规划之斐波那契数列模型
|
算法
趣味算法-神奇的兔子数列
趣味算法-神奇的兔子数列
|
算法
数列极差(大根堆的删和贪心算法模板)
数列极差(大根堆的删和贪心算法模板)
69 0
|
机器学习/深度学习 算法
蓝桥杯:递推算法 递归算法 例题:斐波纳契数列
蓝桥杯:递推算法 递归算法 例题:斐波纳契数列
67 0
|
算法 Python
算法创作|规则数列计算解决方法
算法创作|规则数列计算解决方法
73 2
下一篇
无影云桌面