随机函数相关题

Rand()
1.拒绝采样
用rand7()实现rand10()
#include <bits/stdc++.h>
using namespace std;

int rand7(){
	return rand() % 7 + 1;
}

int rand10(){
	// (randX - 1) * Y + rand7() 可以实现randX_Y()
	while (true){
		int a = rand7();
		int b = rand7();
		int num = (a - 1) * 7 + b;
		if (num <= 40) return num; // 此时拒绝采样的击中率是40/49

		// 此时a相当于是rand9()
		a = num - 40
		b = rand7();
		num = (a - 1) * 7 + b;
		// 此时拒绝采样的击中率为60/63,算上上次未击中,此时到达当前这步的概率是9/49 * 60/63
		if (num <= 60) return num;

		// 此时a相当于rand3();
		a = num - 60;
		b = rand7();
		num = (a - 1) * 7 + b;
		// 当前击中率20/21,到达当前这步的概率9/49 * 3/63 * 20/21 
		if (num <= 20) return num;
	}
	// while循环的执行一次的概率是40/49 + 9/49 * 60/63 + 9/49 * 3/63 * 20/21
	return -1;
}

int main(void){
	// 通过rand()7实现rand()10并保证概率相等
	int ans = rand10();
	cout << ans << "\n";
	return 0;
}
参考LeetCode

470.用Rand7()实现Rand10()

2.蓄水池抽样

  能解决输入过大,导致无法一次将所有数据输入时,如何保证每个元素被取到的概率是一样的情况。
  如果取一个元素:结论就是,对于当前第i个元素,以1/i概率将已经选取的值替换为当前值,以(1 - 1/i)的概率保留已经选到的值。
  如果取k个元素:结论就是,对于当前第i个元素,以k/i概率将已经选取的值替换为当前值,以(1 - k/i)概率保留已经选取的值。
  至于证明请参考蓄水池抽样证明

参考LeetCode

398.随机数索引
382.链表随机节点

其他题
多数元素

  给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
  你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:

输入:[3,2,3]
输出:3
示例 2:

输入:[2,2,1,1,1,2,2]
输出:2

进阶:
尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

注意:要求众数必须严格大于数组个数的一半。
对于多数元素这题,有两种解法让我觉得很棒。

  1. 随机化的方法 随机化的方法使用高等数学中级数趋向无穷的思想来证明最多取两次即可,那么满足线性时间复杂度。
  2. (Boyer-Moore 算法)摩尔投票法 摩尔投票法利用了众数必须过半的思想来解决该问题。
参考LeetCode

169.多数元素官方题解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值