算法-随机不重复数列生成
今天上班的时候网上看到题目很简单,题目是这样的:给定一个正整数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(); } } } |
作者:FlyElephant
出处:http://www.cnblogs.com/xiaofeixiang
说明:博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用,博客所有权归本人和博客园所有,如有转载请在显著位置给出博文链接和作者姓名,否则本人将付诸法律。
出处:http://www.cnblogs.com/xiaofeixiang
说明:博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用,博客所有权归本人和博客园所有,如有转载请在显著位置给出博文链接和作者姓名,否则本人将付诸法律。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述