题目描述
给定方法 rand7 可生成 [1,7] 范围内的均匀随机整数,试写一个方法 rand10 生成 [1,10] 范围内的均匀随机整数。
官方题解
整体思路
调用两次rand7作乘积,可以生成49个结果(包括重复的),在这49个数中选取第1~40个数,分别映射4次1~10。
两个关键点
- 如何选取前40个数。注意这里的“前40个数”,并不是数值上小于40,而是id小于40的
- 获得id后,如何映射到1~10上
解体步骤
- 获取乘积结果id
- 建立7*7的矩阵
- 假定排序规则:在这个7*7的矩阵中从左至右、从上至下顺序从1开始排列,那么第row行、第col列的id就是
(row - 1) + col
- 映射到1~10上
- 40个数,完全映射到1~10上,所以1~10中每个数被4个数映射。通过
1 + (id - 1) % 10
可以求解,类似于进制。
- 40个数,完全映射到1~10上,所以1~10中每个数被4个数映射。通过
代码
class Solution {
public:
int rand10() {
int row, col, id;
do{
col = rand7();
row = rand7();
id = col + (row - 1) * 7;
}while(id > 40);
return 1 + (id - 1) % 10;
}
};
其他
- 为什么是rand7 * rand7,而不是rand7 + rand7?
当然可以rand7 + rand7,加减乘除都ok,实际上在解题过程中都没有用到具体的乘积结果,真正用到的是构造的二维矩阵。所以这道题的本质是通过升维用特征向量A[1, …, 7]表示特征向量B[1, …, 10]。 - 如何提高计算效率?
减少舍弃的数字个数,比如现在的解法是49个数舍弃9个,那么对于舍弃的9个,可以进一步调用rand7,生成7*9=63个数,舍弃3个,再对这3个调用一次rand7,从21中舍弃1个。(官方题解) - 获取前40个数id的方法
这种思路简直和计算分割任务混淆矩阵的思路完全一致。在深度学习任务中,混淆矩阵是指以预测类别和真值类别分别作为纵坐标和横坐标的一个矩阵,用于计算模型的查全率和查准率。
分割任务的混淆矩阵是这样计算的:根据总类别数列一个混淆矩阵,然后对每个像素的预测/真值类别进行计数。某3D点云分割任务的混淆矩阵计算代码如下:def fast_hist(pred, label, n): """ pred: (points, 1) 预测 label: (points, 1) 真值 n:类别个数 """ k = (label >= 0) & (label < n) bin_count = np.bincount( n * label[k].astype(int) + pred[k], minlength=n ** 2) return bin_count[:n ** 2].reshape(n, n)