如何以最少rand()调用为100×100零矩阵随机填充100个1?
解决方案:用一维映射+Fisher-Yates变种实现无重复随机选择
当然可以做到!而且这个思路能通用到任意m×n的二维矩阵场景,刚好只需要100次rand()调用就完成填充,完全不会出现重复选位置的问题。
核心思路:二维坐标转一维索引 + 动态缩小可选范围
我们可以把二维矩阵的所有位置映射成连续的一维整数,然后用不需要完整洗牌的Fisher-Yates算法变种,每次从剩余未选的位置里随机挑一个,选完后就把该位置从可选池里移除——全程不需要检查位置是否已被填充,也不会重复调用rand()。
具体步骤(针对100×100矩阵)
二维转一维映射:把矩阵的每个位置(x,y)转换成一个唯一的一维索引,公式为:
idx = x * 100 + y // 行优先,x是行号,y是列号这样整个100×100矩阵就对应0到9999的连续整数(共10000个位置)。
动态随机选择:
- 初始时,可选位置总数
total = 100*100 = 10000 - 循环100次(刚好对应要填充的100个1):
- 调用
rand()生成一个0到total-1之间的随机数r - 把
r转回到二维坐标:x = r // 100,y = r % 100 - 将
M[x][y]设为1 - 把
total减1——这一步相当于把刚选的位置从可选池里移除,下次rand()的范围自动缩小,不会再选到已标记的位置
- 调用
- 初始时,可选位置总数
伪代码示例
// 初始化100×100矩阵全为0 int M[100][100] = {0}; int total_positions = 100 * 100; int target_count = 100; for (int i = 0; i < target_count; i++) { // 生成当前剩余可选位置中的随机索引 int rand_idx = rand() % total_positions; // 转换为二维坐标 int x = rand_idx / 100; int y = rand_idx % 100; // 标记为1 M[x][y] = 1; // 可选位置总数减1,排除已选位置 total_positions--; }
通用化到任意二维矩阵
不管你的矩阵是m行n列,要选择k个不重复的随机位置(k ≤ m×n),只需要调整几个参数:
- 总可选位置数
total = m * n - 二维转一维的公式:
idx = x * n + y(行优先),或者idx = y * m + x(列优先,根据你的需求选择) - 转回到二维坐标:
x = idx // n,y = idx % n(对应行优先的映射)
为什么这个方法能保证100次rand()调用?
每次循环只调用一次rand(),刚好循环100次就完成所有填充。而且因为每次选完后都会缩小可选范围,相当于从剩余的未选位置里随机挑选,完全不会出现重复选中已填充位置的情况,也就不需要额外调用rand()来重试。
内容的提问来源于stack exchange,提问作者Sazzad Hissain Khan
相关产品推荐
相关产品推荐

