生成随机数|打乱数组 问题

本文讨论了如何从0到n-1的整数中高效地随机选择k个数的问题,以及如何随机打乱一个数组。文中介绍了《编程珠玑》中的解决方案,通过概率算法避免了重复生成的数,并提供了C++实现。同时,提到了数组完美洗牌的思路,即从数组的第一个元素开始,依次与后面的元素随机交换,以达到均匀打乱的效果。
摘要由CSDN通过智能技术生成

问题描述:

从0-n-1这n个数中任意选出k个数(0<=k<=n)。

前提:我们认为系统提供的随机函数是真正随机的。


盛大面试的时候被问过类似的问题,当时使用的是蛮力方法:

维护一个set容器,每次生成一个0-n-1之间任意的数,然后添加到set中,直到set的容量达到k。

这样做的问题:如果这次生成的数和上次生成的一样,则该次无效,没有添加到set中去。

如果n较大,k与n比较接近,比如n=1000;k=996,最后几个数的生成将会很困难。效率非常低。


《编程珠玑》12章给出了高效的解法,思路如下:

举个简单的例子,假设n=5,k=2.则选择第一个整数0的概率为2/5,则程序为:


                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
好的,您的问题是如何使用C语言生成不重复的0-200的随机数并存入数组,然后进行选择排序,再进行二分查找。下面是代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> void selection_sort(int arr[], int size) { int i, j, min, temp; for (i = 0; i < size - 1; i++) { min = i; for (j = i + 1; j < size; j++) { if (arr[j] < arr[min]) { min = j; } } if (min != i) { temp = arr[i]; arr[i] = arr[min]; arr[min] = temp; } } } int binary_search(int arr[], int size, int key) { int low = 0, high = size - 1, mid; while (low <= high) { mid = (low + high) / 2; if (arr[mid] == key) { return mid; } else if (arr[mid] < key) { low = mid + 1; } else { high = mid - 1; } } return -1; } int main() { int i, j, temp, size = 200; int arr[size]; srand(time(NULL)); // 设置随机数种子 for (i = 0; i < size; i++) { arr[i] = i; } for (i = 0; i < size; i++) { j = rand() % size; // 生成0-199的随机数 temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; // 交换元素,打乱数组顺序 } selection_sort(arr, size); // 进行选择排序 int key = 51; // 要查找的元素 int index = binary_search(arr, size, key); // 进行二分查找 if (index != -1) { printf("元素%d在数组的第%d个位置\n", key, index + 1); } else { printf("元素%d不在数组中\n", key); } return 0; } ``` 代码解析: 1. 首先定义了两个函数,一个是选择排序,一个是二分查找。 2. 在主函数中定义了一个大小为200的数组arr,使用srand(time(NULL))生成随机数种子,然后使用两个for循环打乱数组顺序,即将数组中的元素随机交换。 3. 调用selection_sort函数进行选择排序,将数组中的元素按照从小到大的顺序排列。 4. 定义要查找的元素key,调用binary_search函数进行二分查找,如果元素存在于数组中,返回元素所在的位置,否则返回-1。 5. 最后根据返回值输出结果。 注意:此代码示例中生成的随机数是包括0和199的,如果您需要生成0到200之间的随机数,可以将rand() % size改为rand() % (size + 1)。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值