算法-隨機不重復數列生成


今天上班的時候網上看到題目很簡單,題目是這樣的:給定一個正整數n,需要輸出一個長度為n的數組,數組元素是隨機數,范圍為0 – n-1,且元素不能重復。比如 n = 3 時,需要獲取一個長度為3的數組,元素范圍為0-2;簡單的理解就是生成一個無序的隨機數組,在路上想了一下回來用三種方式方式實現了一下;OC實現了一下,文章最末尾順便有C#的是實現方法;

永遠的While

while基本上學過語言的最開始的流程分支語句都會涉及到while,如果存在就一直隨機,不存在就跳出判斷,一般最開始想到都是這樣方法:

+ (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;
}

 調用方式:

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

數組篩選

第二種方式其實說起來寫代碼葉遇到過這種情況,有點類似於從箱子中取球,放回去和不回去的這種模式,如果箱子中的每個球顏色都不一樣就是取出來就不放回去,那么取的下一個一定和之前的顏色不一樣,具體實現:

+ (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是尾部交換,原理是一樣的:

+(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;
}

 這時我第一次寫的時候用的代碼,細心的可能發現定義了兩個數組,其實沒有必要,一個就夠,下面的是改進代碼:

+(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;
}

 調用方式同之前的一樣:

  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#版本代碼

 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();
        }
 
 
    }
}
  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM