C++二分查找:统计点对的数目
本题其它解法
C++双指针算法:统计点对的数目
本周推荐阅读
C++二分算法:得到子序列的最少操作次数
本文涉及的基础知识点
二分查找算法合集
题目
给你一个无向图,无向图由整数 n ,表示图中节点的数目,和 edges 组成,其中 edges[i] = [ui, vi] 表示 ui 和 vi 之间有一条无向边。同时给你一个代表查询的整数数组 queries 。
第 j 个查询的答案是满足如下条件的点对 (a, b) 的数目:
a < b
cnt 是与 a 或者 b 相连的边的数目,且 cnt 严格大于 queries[j] 。
请你返回一个数组 answers ,其中 answers.length == queries.length 且 answers[j] 是第 j 个查询的答案。
请注意,图中可能会有 多重边 。
示例 1:
输入:n = 4, edges = [[1,2],[2,4],[1,3],[2,3],[2,1]], queries = [2,3]
输出:[6,5]
解释:每个点对中,与至少一个点相连的边的数目如上图所示。
answers[0] = 6。所有的点对(a, b)中边数和都大于2,故有6个;
answers[1] = 5。所有的点对(a, b)中除了(3,4)边数等于3,其它点对边数和都大于3,故有5个。
示例 2:
输入:n = 5, edges = [[1,5],[1,5],[3,4],[2,5],[1,3],[5,1],[2,3],[2,5]], queries = [1,2,3,4,5]
输出:[10,10,9,8,6]
参数范围:
2 <= n <= 2 * 104
1 <= edges.length <= 105
1 <= ui, vi <= n
ui != vi
1 <= queries.length <= 20
0 <= queries[j] < edges.length
分析
时间复杂度
每个查询的时间复杂度是O(nlogn+m)。m的边数。
步骤
每个查询分两步:
一,和a或b相连的边数,严格大于iQue的点对数量。注意,同时和a和b相连算两次,只和a或b相连算一次。
二,枚举各边。如果符合第一步,扣除本边数量后,不再符合题意则减掉。本解法在预处理阶段确保v[0]大于v[1]。
注意:本解题将a和b都减一,这样其范围为:[0,n)。
变量解释
m_vNodeToCount | m_vNodeToCount[i]=x,有x条边和i相连 |
m_vCounts | m_vNodeToCount的升序,第一步只考虑和a或b相连的边数,不需要知道a和b的具体值 |
m_mMaskCount | 各边数量,key是a和b的编码,value是数量 |
代码
核心代码
class Solution {
public:vector<int> countPairs(int n, vector<vector<int>>& edges, vector<int>& queries) { m_iN = n;m_vNodeToCount.resize(n);for (auto& v : edges){if (v[0] < v[1]){swap(v[0], v[1]);}v[0]--;v[1]--; m_vNodeToCount[v[0]]++;m_vNodeToCount[v[1]]++;m_mMaskCount[Mask(v[0], v[1])]++;}m_vCounts = m_vNodeToCount;sort(m_vCounts.begin(), m_vCounts.end());vector<int> vRet;for (const auto& que : queries){vRet.emplace_back(Query(que));}return vRet;}int Query(int iQue)const{int iNum = 0;// 包括a或b的边数大于iQue的数量,(a,b)和(b,a)会重复结算for (auto left = m_iN - 1; left >= 0 ; left--){ iNum += m_vCounts.end() - std::upper_bound(m_vCounts.begin()+left+1, m_vCounts.end(),iQue-m_vCounts[left]);}//扣处重复数量for (const auto& [iMask, iNum1] : m_mMaskCount){auto [a, b] = Parse(iMask);const int tmp = m_vNodeToCount[a] + m_vNodeToCount[b] - iQue;if (tmp > 0 ){if (tmp <= iNum1){iNum--;}}} return iNum;}int Mask(int a, int b){return a * m_iUnit + b;}std::pair<int,int> Parse(const int iMask)const{return std::make_pair(iMask / m_iUnit, iMask % m_iUnit);}const int m_iUnit = 1000 * 100;unordered_map<int, int> m_mMaskCount;vector<int> m_vNodeToCount;vector<int> m_vCounts;int m_iN;
};
测试用例
template <class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template <class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}
}int main()
{int n;vector<vector<int>> edges;vector<int> queries;vector<int> res;{ n = 4;edges = { {1,2},{2,4},{1,3},{2,3},{2,1} };queries = { 2,3 };Solution slu;res = slu.countPairs(n, edges, queries);Assert(res, vector<int>{6, 5});}{n = 5;edges = { {1,5},{1,5},{3,4},{2,5},{1,3},{5,1},{2,3},{2,5} };queries = { 1,2,3,4,5 };Solution slu;res = slu.countPairs(n, edges, queries);Assert(res, vector<int>{10, 10, 9, 8, 6});}//CConsole::Out(res);
}
2023年3月版代码
class Solution {
public:
vector countPairs(int n, vector<vector>& edges, vector& queries) {
m_vDeg.resize(n + 1);
m_iN = n;
for (const auto& v : edges)
{
m_vDeg[v[0]]++;
m_vDeg[v[1]]++;
m_mEdgeNums[min(v[0], v[1])m_llMul + max(v[0], v[1])]++;
}
vector vRet;
for (const auto& q : queries)
{
vRet.push_back(Query1(q) - Query2(q));
}
return vRet;
}
long long Query1(int iQuery)
{
CTreeArr tree(1000100 + 1);
long long iRet = 0;
for (int i = 1; i <= m_iN; i++)
{
const int iMin = iQuery - m_vDeg[i];
const int iLessEqualNum = (iMin>=0) ? tree.Sum(iMin ) : 0;
iRet += (i - 1) - iLessEqualNum;
tree.Add(m_vDeg[i],1);
}
return iRet;
}
long long Query2(int iQuery)
{
long long llSub = 0;
for (auto it : m_mEdgeNums)
{
const int iNum1 = m_vDeg[it.first%m_llMul] + m_vDeg[it.first/m_llMul];
if (iNum1 <= iQuery)
{
continue;
}
if (iNum1 - it.second <= iQuery)
{
llSub++;
}
}
return llSub;
}
long long m_llMul = 1000 * 100;
vector m_vDeg;
std::unordered_map<long long, int> m_mEdgeNums;
int m_iN;
};
2023年7月版代码
class Solution {
public:
vector countPairs(int n, vector<vector>& edges, vector& queries) {
m_vConnectNums.resize(n + 1);
m_n = n;
for (const auto& v : edges)
{
m_vConnectNums[v[0]]++;
m_vConnectNums[v[1]]++;
m_mEdgeMaskNum[ToMask(v)]++;
}
m_iMaxSize = *std::max_element(m_vConnectNums.begin(), m_vConnectNums.end());
vector vRet;
for (const auto& que : queries)
{
vRet.emplace_back(Query(que));
}
return vRet;
}
int Query(const int iQuery)
{
CTreeArr treeArr(m_iMaxSize + 1);
int iRet = 0;
for (int i = 1; i <= m_n; i++)
{
const int iCurSize = m_vConnectNums[i];
int iMin = iQuery - iCurSize;
if (iMin < 0)
{
iRet += (i - 1);
}
else if (iMin >= m_iMaxSize)
{
}
else
{
const int iSum1 = treeArr.Sum(m_iMaxSize);
const int iSum2 = treeArr.Sum(iMin);
iRet += iSum1 - iSum2;
}
treeArr.Add(iCurSize, 1);
}
for (const auto& it : m_mEdgeMaskNum)
{
const int iNum = m_vConnectNums[it.first / 100000] + m_vConnectNums[it.first % 100000];
if (iNum <= iQuery)
{
continue;
}
if (iNum - it.second <= iQuery)
{
iRet–;
}
}
return iRet;
}
int ToMask(const vector& v)
{
return min(v[0], v[1]) * 100000 + max(v[0], v[1]);
}
std::unordered_map<int, int> m_mEdgeMaskNum;
vector m_vConnectNums;
int m_n;
int m_iMaxSize;
};
扩展阅读
视频课程
有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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
我想对大家说的话 |
---|
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
相关文章:

C++二分查找:统计点对的数目
本题其它解法 C双指针算法:统计点对的数目 本周推荐阅读 C二分算法:得到子序列的最少操作次数 本文涉及的基础知识点 二分查找算法合集 题目 给你一个无向图,无向图由整数 n ,表示图中节点的数目,和 edges 组成…...
播放器开发(二):了解FFmpeg与SDL常用对象和函数
学习课题:逐步构建开发播放器【QT5 FFmpeg6 SDL2】 前言 这一篇内容就是简单的了解一遍一些常用的函数名称和作用,混个眼熟。 能看源码的就去看源码!!! 能看源码的就去看源码!!! …...

【数据库】基于排序算法的去重,集合与包的并,差,交,连接操作实现原理,执行代价以及优化
基于两趟排序的其它操作 专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏…...

Redis 主从架构,Redis 分区,Redis哈希槽的概念,为什么要做Redis分区
文章目录 Redis 主从架构redis replication 的核心机制redis 主从复制的核心原理过程原理Redis集群的主从复制模型是怎样的?生产环境中的 redis 是怎么部署的?机器是什么配置?你往内存里写的是什么数据?说说Redis哈希槽的概念&…...

极客大挑战2023 Web方向题解wp 全
最后排名 9/2049。 玩脱了,以为28结束,囤的一些flag没交上去。我真该死啊QAQ EzHttp 前言:这次极客平台太安全了谷歌不给抓包,抓包用burp自带浏览器。 密码查看源码->robots.txt->o2takuXX’s_username_and_password.txt获…...

kafka开发环境搭建
文章目录 1 安装java环境1.1 下载linux下的安装包1.2 解压缩安装包1.3 解压后的文件移到/usr/lib目录下1.4 配置java环境变量 2 kafka的安装部署2.1 下载安装kafka2.2 配置和启动zookeeper2.3 启动和停止kafka 1 安装java环境 1.1 下载linux下的安装包 (1…...

Python大数据考题
Python大数据考题: 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测开 测开的话,你就得学数据库,sql,oracle,尤其sql要…...

才聚免费为你招聘,用人单位看过来!
才聚团队从1998年开始从事项目管理的推广工作,20多年来培训学员超30万人次,分布全国各地、服务企业超过5000家。拥有大批 PMP (项目管理专业人员资格) NPDP(产品经理国际资格) 软考 (信息系统…...

【SpringCloud】微服务的扩展性及其与 SOA 的区别
一、微服务的扩展性 由上一篇文章(没看过的可点击传送阅读)可知, 微服务具有极强的可扩展性,这些扩展性包含以下几个方面: 性能可扩展:性能无法完全实现线性扩展,但要尽量使用具有并发性和异步…...

从零带你底层实现unordered_map (2)
💯 博客内容:从零带你实现unordered_map 😀 作 者:陈大大陈 🚀 个人简介:一个正在努力学技术的准C后端工程师,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家…...
打造企业AI数字人专属IP的重要性
在数字化时代,企业数字人专属IP的打造成为了企业品牌建设的重要组成部分。企业数字人专属IP是指是利用人工智能技术实现与真人直播形象的1:1克隆,即克隆出一个数字化的真人形象,作为独有的企业数字人形象,可以用于产品推广、品牌宣…...

docker容器的生命周期管理常用命令
容器的生命周期管理命令 docker create :创建一个新的容器但不启动它 docker create nginx docker run :创建一个新的容器并运行一个命令 常用选项: 常用选项1. --add-host:容器中hosts文件添加 host:ip 映射记录 2. -a, --attach&#…...
CF 1900B Laura and Operations 学习笔记
原题链接 传送门 题意 输入三个数字a,b,c表示1,2,3的数目,也就是说有a个1,b个2,c个3,每一次可以删除两个不同的数字,增加一个剩下的数字,比如说删除1和3,增加2&#x…...
Linux学习笔记6-串口应用
到现在为止都是在开发板上运行的裸机程序,相当于之前学习STM32单片机时走过的路,还没有真正进入到核心的驱动开发部分,但这都是基础,所以慢慢来不着急。 接下来进入串口通信的学习,和GPIO一样,也是和单片机…...
ubuntu下如何查看.gz压缩包中的内容,以及grep过滤查找文件中的某些内容
1、查看压缩包file.gz中的全部内容 $ zcat file.gz 2、对一个.gz的压缩包解压缩 $ gunzip file.gz 3、过滤查找文件中的某些内容 $ grep "Hello" file.txt 注:我通常先解压,然后再grep 4、过滤查找文件中的内容,并显示其上下3行…...

AI 重构工业制造的故事 我们从大模型开始讲起
在数字化浪潮的推动下,工业制造领域正经历着一场前所未有的变革。人工智能(AI)作为这场变革的关键推动者之一,正以惊人的速度颠覆传统制造业。而大模型作为AI时代最先进的科技工具之一,或将成为引领这场变革的利器&…...

easyExcel 注解开发 快速以及简单上手 以及包含工具类
easyExcel 简单快速使用 1. mevan 这里版本我这里选的是 poi 4.1.2和 ali的easyexcel 的 3.3.1。 因为阿里easy是根据poi的依赖开发的有关系,两者需要对应要不然就会有很多bug和错误在运行时发生。需要版本对应,然而就是easy的代码也会有bug这个版本是比…...

VS2010配置opencv2.4.10
1.下载opencv2.4.10,百度网盘链接如下: 链接:https://pan.baidu.com/s/1UdoQJbRUEB_G2urT703xYQ 提取码:7lbd 2.运行opencv-2.4.10.exe,将文件提取到一个自定义目录里: 3.添加系统环境变量 在“系统变量…...
Android:控制按键灯亮灭【button-backlight】
/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 1.导包 import java.io.DataOutputStream; import java.io.FileOutputStream; Handler mHandler3; 2.新建handler对象 public void init(Context context, IWindowManager windowMan…...

1、nmap常用命令
文章目录 1. 主机存活探测2. 常见端口扫描、服务版本探测、服务器版本识别3. 全端口(TCP/UDP)扫描4. 最详细的端口扫描5. 三种TCP扫描方式(1)TCP connect 扫描(2)TCP SYN扫描(3)TCP …...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...