C++二分算法:黑名单中的随机数

news2024/11/24 18:40:57

涉及知识点

二分查找

题目

给定一个整数 n 和一个 无重复 黑名单整数数组 blacklist 。设计一种算法,从 [0, n - 1] 范围内的任意整数中选取一个 未加入 黑名单 blacklist 的整数。任何在上述范围内且不在黑名单 blacklist 中的整数都应该有 同等的可能性 被返回。
优化你的算法,使它最小化调用语言 内置 随机函数的次数。
实现 Solution 类:
Solution(int n, int[] blacklist) 初始化整数 n 和被加入黑名单 blacklist 的整数
int pick() 返回一个范围为 [0, n - 1] 且不在黑名单 blacklist 中的随机整数
示例 1:
输入
[“Solution”, “pick”, “pick”, “pick”, “pick”, “pick”, “pick”, “pick”]
[[7, [2, 3, 5]], [], [], [], [], [], [], []]
输出
[null, 0, 4, 1, 6, 1, 0, 4]
解释
Solution solution = new Solution(7, [2, 3, 5]);
solution.pick(); // 返回0,任何[0,1,4,6]的整数都可以。注意,对于每一个pick的调用,
// 0、1、4和6的返回概率必须相等(即概率为1/4)。
solution.pick(); // 返回 4
solution.pick(); // 返回 1
solution.pick(); // 返回 6
solution.pick(); // 返回 1
solution.pick(); // 返回 0
solution.pick(); // 返回 4
参数范围
1 <= n <= 109
0 <= blacklist.length <= min(105, n - 1)
0 <= blacklist[i] < n
blacklist 中所有值都 不同
pick 最多被调用 2 * 104 次

错误解法 空间复杂度超出

分析

枚举[0,n)如果是黑名单种扔掉,否则放到m_vValue中。n 最大值10^9,必定超时。

代码

class Solution {
public:
Solution(int n, vector& blacklist) {
sort(blacklist.begin(), blacklist.end());
auto it = blacklist.begin();
for (int i = 0; i < n; i++)
{
while ((it != blacklist.end()) && (*it < i ))
{
++it;
}
if ((it != blacklist.end()) && (*it == i))
{
continue;
}
m_vValue.emplace_back(i);
}
srand(time(nullptr));
}
int pick() {
return m_vValue[rand() % m_vValue.size()];
}
vector m_vValue;
};

正确解法

分析

令黑名单的数量是m,那可以可以生成的数量是m_k=n-m。我们随机生成[0,m_k)的数字r,如果r在黑名单中则替换,否则直接返回r。

变量解释

it指向黑名点中首个大于等于m_k的数。[…,it)需要替换,替换的数必须大于等于m_k,且不能在[it,…)中,且不能相互重复。相互重复好解决:iMay自增,初始值等于m_k,这可以保证大于等于m_k。
tNeedReplace指向需要替换的值
itBlackList指向大于等于iMay的最小值。

注意

初始情况,iMay小于等于 *itBlackList ,如果两者相等则则itBalck++,所以iMay永远不会大于 *itBlackList

代码

class Solution {
public:
	Solution(int n, vector<int>& blacklist) {
		sort(blacklist.begin(), blacklist.end());
		const int m = blacklist.size();
		m_k = n - m;
		const auto it = std::lower_bound(blacklist.begin(), blacklist.end(), m_k);
		auto itNeedReplace = blacklist.begin();
		auto itBlackList = it;
		int iMay = m_k;
		for (; itNeedReplace != it ; ++itNeedReplace)
		{
			while ((itBlackList != blacklist.end()) && (iMay == *itBlackList ))
			{
				iMay++;
				++itBlackList;
			}
			m_mReplace[*itNeedReplace] = iMay++;
		}
		srand(time(nullptr));
	}
	int pick() {
		const int r = rand() % m_k;
		if (m_mReplace.count(r))
		{
			return m_mReplace[r];
		}
		return r;
	}
	std::unordered_map<int,int> m_mReplace;
	int m_k;
};

2023年3月版旧代码

struct SGroupInfo
{
SGroupInfo(int tBegin, int tLen, int tTotalLen)
{
begin = tBegin;
len = tLen;
totalLen = tTotalLen;
}
int End()const
{
return begin + len - 1;
}
int begin;
int len;
int totalLen;
};
class Solution {
public:
Solution(int N, vector& blacklist) {
m_iN = N;
m_iMaxRand = N - blacklist.size();
srand(time(nullptr));
std::sort(blacklist.begin(), blacklist.end());
if (blacklist.empty())
{
m_v.emplace_back(0, N, N);
return;
}
for (int i = 0; i < blacklist.size();i++)
{
const auto& n = blacklist[i];
if (0 == i )
{
const int len = n;
if (len > 0)
{
m_v.emplace_back(0, len, len);
}
}
else
{
const int len = n - blacklist[i-1] - 1;
if (len > 0)
{
const int iPreLen = m_v.empty() ? 0 : m_v.back().totalLen;
m_v.emplace_back(blacklist[i - 1] + 1, len, iPreLen + len);
}
}
}
const int len = m_iN - 1 - blacklist.back();
if (len > 0)
{
const int iPreLen = m_v.empty() ? 0 : m_v.back().totalLen;
m_v.emplace_back(blacklist.back() + 1, len, iPreLen + len);
}
}
int pick() {
const int index = rand() % m_iMaxRand;
auto it = std::lower_bound(m_v.begin(), m_v.end(), index+1, [](const SGroupInfo& group, const int& x2)
{return group.totalLen < x2; });
return it->begin + (index - (it->totalLen - it->len));
}
vector m_v;
int m_iN;
int m_iMaxRand;
};

2023年8月旧代码

class Solution {
public:
Solution(int n, vector& blacklist) {
m_iPickNum = n - blacklist.size();
std::set setHas(blacklist.begin(), blacklist.end());
int iReplace = m_iPickNum;
for (const auto& black : blacklist)
{
if (black >= m_iPickNum)
{
continue;
}
while (setHas.count(iReplace))
{
iReplace++;
}
m_mReplace[black] = iReplace++;
}
srand(time(nullptr));
}
int pick() {
int iRand = rand() % m_iPickNum;
if (m_mReplace.count(iRand))
{
return m_mReplace[iRand];
}
return iRand;
}
int m_iPickNum;
std::unordered_map<int, int> m_mReplace;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院
,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

鄙人想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
墨家名称的来源:有所得以墨记之。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1183166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux | 磁盘文件与动静态库

目录 前言 一、了解磁盘 1、磁盘结构 2、磁盘划分 3、inode与文件名的关系 二、软链接与硬链接 1、如何创建软连接与硬链接文件 2、理解软连接 3、理解硬链接 三、动态库与静态库 1、静态库 &#xff08;1&#xff09;静态库的制作 &#xff08;2&#xff09;静态…

第九章 排序【数据结构】【精致版】

第九章 排序【数据结构】【精致版】 前言版权第九章 排序9.1 概述9.2 插入类排序9.2.1 直接插入排序**1-直接插入排序.c** 9.2.2 折半插入排序**2-折半插入排序.c** 9.2.3 希尔排序 9.3 交换类排序9.3.1冒泡排序**4-冒泡排序.c** 9.3.2 快速排序**5-快速排序.c** 9.4 选择类排…

Blocking waiting for file lock on the registry index 问题解决

问题表现&#xff1a; cargo build时一直卡在Blocking waiting for file lock on the registry index。 解决方法&#xff1a; 1、之前在linux下出现过一次&#xff0c;采用这种方法解决了&#xff1a;rust - Cargo build hangs with " Blocking waiting for file lock…

【已解决】Windows易升报错0xa0000400,一键修复,无损升级至Windows 10/11 22H2

笔者之前在使用的Windows 10版本是企业版LTSC 1809&#xff0c;想升级到22H2版&#xff0c;不想重装系统和所有软件&#xff0c;听说微软官方的“Windows易升”软件可以无损升级&#xff0c;下载这个软件运行之后&#xff0c;卡在第一步&#xff1a; 软件提示&#xff1a;“若要…

SPSS距离分析

1.距离分析 距离分析在统计学和数据科学中指的是评估和量化对象&#xff08;如观测点、个体、案例等&#xff09;之间差异的过程。在数据集中&#xff0c;每个对象通常由一系列的属性或变量表示。距离分析的目的是为了衡量这些对象在多维空间中的相对位置&#xff0c;通常用于…

MSQL系列(十四) Mysql实战-SQL语句 left join inner join On和Where语句的区别

Mysql实战-SQL语句On和Where语句的区别 前面我们讲解了Join的底层驱动表 选择原理&#xff0c;也知道了基本的内连接外连接两种SQL查询表连接方式 但是我们再查询多表的时候on和where语句到底有什么区别? where是过滤条件 ,不满足where的一定不会出现在结果中on是连接条件, …

Leetcode—2731.移动机器人【中等】

2023每日刷题&#xff08;二十二&#xff09; Leetcode—2731.移动机器人 算法思路 参考自灵茶山艾府 实现代码 class Solution { public:const int MOD 1e9 7;int sumDistance(vector<int>& nums, string s, int d) {int n nums.size();vector<long long…

使用<a>标签进行文件下载出现文件名称乱码、文件名变下划线

在使用a标签下载文件时出现了如图所示文件名称显示错误&#xff0c;原因是因为文件中包含中文导致乱码 解决方法使用axios配合Blob&#xff0c;如果项目中没有安装或者不想安装axios使用Ajax跟fetch也是一样可以解决&#xff1a; 使用axios&#xff08;记得引入axios&#xff0…

JJJ:PCI / PCIE 的一些术语和概念

转发事务和非转发事务 在PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;总线中&#xff0c;存在两种类型的事务&#xff1a;转发事务和非转发事务。 1、转发事务&#xff08;Forwarded Transactions&#xff09;&#xff1a;转发事务是指从一个PCIe…

openvpn使用

如何使用OpenVPN搭建局域安全网_宝塔搭建vpn_幸识SQ的博客-CSDN博客 OpenVPN在CentOS7中最简单的搭建局域网_哔哩哔哩_bilibili 最终的效果是&#xff0c;如果安装好服务端后&#xff0c;会生成一个文件&#xff0c;要用到客户端。 客户端安装后&#xff0c;会多个IP 这样&…

关于unity中 编辑器相关逻辑的记录

prefab 在场景中 , 用这个方法可以获取它的磁盘路径: [MenuItem("Gq_Tools/↓获取prefab路径")] public static void SaveDecalParameters() { var objs Selection.objects; var obj objs[0] as GameObject; Object parentObject Prefab…

Amazon MSK 基于 S3 的数据导出、导入、备份、还原、迁移方案

Amazon MSK&#xff08;Amazon Managed Streaming for Apache Kafka&#xff09;是 Amazon 云平台提供的托管 Kafka 服务。在系统升级或迁移时&#xff0c;用户常常需要将一个 Amazon MSK 集群中的数据导出&#xff08;备份&#xff09;&#xff0c;然后在新集群或另一个集群中…

Linux之打印函数调用依赖关系(六十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

extractvalue报错注入理论及实战

报错注入 什么是报错注入 构造语句&#xff0c;让错误信息中夹杂可以显示数据库内容的查询语句&#xff0c;返回报错提示中包括数据库中的内容 如上图所示&#xff0c;通过group by的报错&#xff0c;我们可以知道列数是多少 输入正确的查询数据库的SQL语句&#xff0c;虽然可…

理解交叉熵(Cross Entropy)

交叉熵&#xff08;Cross-Entropy&#xff09;是一种用于衡量两个概率分布之间的距离或相似性的度量方法。在机器学习中&#xff0c;交叉熵通常用于损失函数&#xff0c;用于评估模型的预测结果与实际标签之间的差异。 在分类问题中&#xff0c;交叉熵损失函数通常用于多分类问…

如何在公文套红过程中设置页码

zOffice的套红功能&#xff0c;是把源文件套入到公文模版的书签中去&#xff0c;将两个文件合成一个&#xff0c;那么源文件的一些设置可能会保留也可能会被重置&#xff0c;那么如何在公文套红中保留页码设置呢&#xff1f;当然是通过zOffice丰富的SDK接口来实现控制了&#x…

WebGL软件项目类型

WebGL&#xff08;Web Graphics Library&#xff09;是一种用于在Web浏览器中渲染3D和2D图形的JavaScript API。它提供了强大的能力&#xff0c;可以用于开发各种类型的项目&#xff0c;包括但不限于以下几种&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xf…

Vue 3 中,watch 和 watchEffect 的区别

结论先行&#xff1a; watch 和 watchEffect 都是监听器&#xff0c;都是用来监听响应式数据的变化并执行相应操作。区别是&#xff1a; watch&#xff1a;需要指明要监听的数据&#xff0c;而且在回调函数中可以获取到属性变化的前后值&#xff1b; 适用于需要精确控制监视…

学习在echarts中优化数据视图dataView样式带表格样式,支持复制功能

学习在echarts中优化数据视图dataView样式 带表格样式 toolbox里有个dataView视图模式&#xff0c;里面的数据没有对整&#xff0c;影响展示效果&#xff0c;情形如下&#xff1a; 像这种标题跟数据没有整齐对应上&#xff0c;看起来乱 改问题解决方案为&#xff0c;option 》…

IO多路复用 Linux C Server-Client 多用户聊天系统

目录 Server-Client mutiplexingServer mutiplexingClient mutiplexing Server-Client 在Linux系统中&#xff0c;IO多路复用是一种机制&#xff0c;它允许一个进程能够监视多个文件描述符&#xff08;sockets、pipes等&#xff09;的可读、可写和异常等事件。这样&#xf…