剑指Offer(数据结构与算法面试题精讲)C++版——day21

剑指Offer(数据结构与算法面试题精讲)C++版——day21

      • 题目一:数据流的第k大数字
      • 题目二:出现频率最高的k个数字
      • 题目三:和最小的k个数对
      • 附录:源码gitee仓库

题目一:数据流的第k大数字

    题目:请设计一个类型KthLargest,它每次从一个数据流中读取一个数字,并得出数据流已经读取的数字中第k(k≥1)大的数字。该类型的构造函数有两个参数:一个是整数k,另一个是包含数据流中开始数字的整数数组nums(假设数组nums的长度大于k)。该类型还有一个函数add,用来添加数据流中的新数字并返回数据流中已经读取的数字的第k大数字。
    例如,当k=3且nums为数组[4, 5, 8, 2]时,调用构造函数创建类型KthLargest的实例之后,第1次调用add函数添加数字3,此时已经从数据流中读取了数字4、5、8、2和3,第3大的数字是4;第2次调用add函数添加数字5时,则返回第3大的数字5。

    如果不考虑时间复杂度那么可以直接暴力处理,直接对每次加入的数据排序,固定返回第k个即可。但是由于这里题意中给出的是数据流,排序的话需要对所有数据处理,空间可能不够用,并且这类型场景都需要考虑时间复杂度。
    分析发现,这里存在类似于堆的结构,比如在大根堆中,可以很方便的找到一组动态变化的数中最大的一个,并且维护的时间复杂度较低。于是借鉴这里的思路,可以构建一个大小固定为k的优先级队列,这k个元素是这组数据中最大的k个元素,并且让这k个数构成一个小根堆,这样每次取出堆顶元素就可以得到第k大的数字。在维护上,C++中有可以使用的库,直接利用库来实现即可,最终得到如下代码:

void initHeap(priority_queue<int, vector<int>, greater<int>> & minHeap,vector<int> arr,int fixSize) {for(int i=0,size=arr.size(); i<size; ++i) {if(minHeap.size()<fixSize) {minHeap.push(arr[i]);} else {int top=minHeap.top();if(arr[i]>top) {minHeap.pop();minHeap.push(arr[i]);}}}
}
int addHeap(priority_queue<int, vector<int>, greater<int>> & minHeap,int num,int k) {int top=minHeap.top();if(num>top) {minHeap.pop();minHeap.push(num);}return minHeap.top();
}

在这里插入图片描述

题目二:出现频率最高的k个数字

    题目:请找出数组中出现频率最高的k个数字。例如,当k等于2时,输入数组[1, 2, 2, 1, 3, 1],由于数字1出现了3次,数字2出现了2次,数字3出现了1次,因此出现频率最高的2个数字是1和2。

    因为这里提到了需要统计每个数的出现频次,因此立即会想到利用map构建hash表结构。现在的关键点在于如何保证拿到<数字,出现次数>的映射关系之后,返回出现频次最高的k个数。和前面的方法一样构建一个大小为k小根堆,如果当前小根堆中的元素个数小于k,直接加入到小根堆中,如果当前的已经有k个元素了,那么取出小根堆堆顶元素判断,如果待加入元素频次高于已有堆顶元素频次,那么新元素入堆。于是得到如下代码:

priority_queue<int, vector<int>,greater<int>> getTopKNum(vector<int> arr,int k) {vector<int> result;map<int,int> countNum;for(int i=0,size=arr.size();i<size;++i){countNum[arr[i]]++;}priority_queue<int, vector<int>,greater<int>> maxHeap;for(const auto& pair:countNum){int key=pair.first;int value=pair.second;if(maxHeap.size()<k){maxHeap.push(key);}else{if(value>maxHeap.top()){maxHeap.push(key);}}}return maxHeap;
}

在这里插入图片描述

    这里需要补充说明,由于这里小根堆中存储的都是<数字,出现次数>的键值key,因此构建的堆中频次只能确定堆顶频次最小。之后依次找出这k个结果的时候,由于小根堆的特点,所以是按照键值key导出的。不能够保证按照频次倒叙排列。由于题目没有对这k个数的输出顺序要求,所以这里直接频次乱序输出即可。如果还要求对这k个数按照频次倒叙输出应该怎么办呢?其实也不难实现,可以将问题简化成知道了一组<数字,出现次数>键值对,需要将这些键值对按照出现次数倒序排序。这样可以使用大根堆来实现,相当于将键值反向,按照出现的次数作为键,将原先的键作为值,由于出现相同次数的值可能对应多个键,因此使用数组存储。得到如下代码:

priority_queue<int, vector<int>> maxHeap;
while(!minHeap.empty()) {int key=minHeap.top();maxMap[countNum[key]].push_back(key);minHeap.pop();
}
priority_queue<int, vector<int>> maxHeap;
for(const auto& pair:maxMap) {int key=pair.first;maxHeap.push(key);
}
while(!maxHeap.empty()) {vector<int> values=maxMap[maxHeap.top()];for(int i=0,size=values.size(); i<size; ++i) {cout<<values[i]<<" ";}maxHeap.pop();
}

题目三:和最小的k个数对

    题目:给定两个递增排序的整数数组,从两个数组中各取一个数字u和v组成一个数对(u,v),请找出和最小的k个数对。例如,输入两个数组[1, 5, 13, 21]和[2, 4, 9, 15],和最小的3个数对为(1,2)、(1,4)和(2,5)。

    由分析可知,这里的依旧可以按照题目一的方式来统计,由于k的数值不确定,可能k的值比较大,包括了两个数组中的所有可能。因此需要遍历两个数组的所有组合。需要考虑一个问题,这样的数对是否可能重复,比如两个数组分别为:[1,2,3]和[1,2,3],两个数组都满足严格递增,答案是否定的,可以利用一个数组作为参照,比如这里固定第一个数组的第一个元素,扫描后面数组的所有元素构成组合,可以得到3种情况,之后偏移第一个数组的指向元素。由于这个过程中得到的数对第一个元素递增,并且在相同第一个元素下,第二个元素同样满足递增,因此最终所有可能的数对不可能重复。结合题目一,这里可以先构建一个大小为k的大根堆,如果一个元素小于根节点,那么说明这个元素需要应该进入k大根堆种替换,最终可以得到如下代码:

void getTopKMin(vector<int>arr1,vector<int> arr2,int k) {map<int,vector<Element>> numMap;priority_queue<Element,vector<Element>,customGreater> maxHeap;int size1=arr1.size(),size2=arr2.size();for(int i=0; i<size1; ++i) {for(int j=0; j<size2; ++j) {cout<<"当前探测:"<<arr1[i]<<" "<<arr2[j]<<endl;if(maxHeap.size()<k) {maxHeap.push(Element(arr1[i],arr2[j]));} else if(sumElement(Element(arr1[i],arr2[j]))<sumElement(maxHeap.top())) {maxHeap.push(Element(arr1[i],arr2[j]));maxHeap.pop();}}}while(!maxHeap.empty()) {Element el=maxHeap.top();cout<<"("<<el.num1<<","<<el.num2<<")"<<" ";maxHeap.pop();}
}

在这里插入图片描述
    另外这里对于C++可以积累一个自定义节点的优先级队列构建方法,还能够自定义优先级队列的大根堆、小根堆比较方法:

struct  Element {int num1;int num2;Element(int a,int b):num1(a),num2(b) {}
};
long long sumElement(Element el) {return el.num1+el.num2;
}
struct customGreater {bool operator()(Element a, Element b) const {return sumElement(a) < sumElement(b);}
};
//用法
priority_queue<Element,vector<Element>,customGreater> maxHeap;

附录:源码gitee仓库

    考虑到有些算法需要模拟数据,如果全部放进来代码显得过长,不利于聚焦在算法的核心思路上。于是把所有的代码整理到了开源仓库上,如果想要看详细模拟数据,可在开源仓库自取:【凌空暗羽/剑指Offer-C++版手写代码】。

    我是【Jerry说前后端】,本系列精心挑选的算法题目均基于经典的《剑指 Offer(数据结构与算法面试题精讲)》。在如今竞争激烈的技术求职环境下,算法能力已成为前端开发岗位笔试考核的关键要点。通过深入钻研这一系列算法题,大家能够系统地积累算法知识和解题经验。每一道题目的分析与解答过程,都像是一把钥匙,为大家打开一扇通往高效编程思维的大门,帮助大家逐步提升自己在数据结构运用、算法设计与优化等方面的能力。
    无论是即将踏入职场的应届毕业生,还是想要进一步提升自身技术水平的在职开发者,掌握扎实的算法知识都是提升竞争力的有力武器。希望大家能跟随我的步伐,在这个系列中不断学习、不断进步,为即将到来的前端笔试做好充分准备,顺利拿下心仪的工作机会!快来订阅吧,让我们一起开启这段算法学习之旅!

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

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

相关文章

NCCL非阻塞non-blocking实现

NCCL (NVIDIA Collective Communications Library) 主要设计用于高性能的集体通信&#xff08;如all-reduce、broadcast等&#xff09;&#xff0c;但其核心函数默认是阻塞式的&#xff08;blocking&#xff09;&#xff0c;即函数返回时操作已完成。不过&#xff0c;你可以通过…

代码随想录算法训练营第60期第二十天打卡

大家好&#xff0c;今天我们继续进入二叉树的章节&#xff0c;二叉树章节应该已经过半了&#xff0c;大家再坚持一下&#xff0c;那么废话不多说&#xff0c;我们继续今天的内容。 第一题对应力扣编号为235的二叉搜索树的最近公共祖先 其实我们上次任务就接触过了二叉树的最近…

8.0 西门子PLC的S7通讯解析

PC与西门子PLC的S7通讯主要有如下几个步骤: 1. TCP的三次握手(由Socket对象自动完成) 2.发送访问请求:COTP 3. 交换通讯信息:setup Commnunication 一、发送访问请求:COTP 比如向PLC请求+以及PLC返回响应的一个实际例子如下: 发送PLC:----> 03 00 00 16 11 E0 …

Nacos-SpringBoot 配置无法自动刷新问题排查

背景 Nacos SpringBoot版本中&#xff0c;提供了NacosValue注解&#xff0c;支持控制台修改值时&#xff0c;自动刷新&#xff0c;但是今天遇见了无法自动刷新的问题。 环境 SpringBoot 2.2.x nacos-client&#xff1a;2.1.0 nacos-config-spring-boot-starter&#xff1a;0…

JAVA | 聚焦 OutOfMemoryError 异常

个人主页 文章专栏 在正文开始前&#xff0c;我想多说几句&#xff0c;也就是吐苦水吧…最近这段时间一直想写点东西&#xff0c;停下来反思思考一下。 心中万言&#xff0c;真正执笔时又不知先写些什么。通常这个时候&#xff0c;我都会随便写写&#xff0c;文风极像散文&…

基于开源技术体系的品牌赛道力重构:AI智能名片与S2B2C商城小程序源码驱动的品类创新机制研究

摘要&#xff1a;在数字经济与实体经济深度融合的背景下&#xff0c;品牌竞争已从单一产品力竞争转向生态化、技术化的赛道力竞争。本文以开源AI大模型、AI智能名片及S2B2C商城小程序源码为核心技术载体&#xff0c;构建"技术赋能-场景贯通-生态协同"三维分析框架&am…

【vue3】购物车实战:从状态管理到用户体验的全流程实现

在电商项目中&#xff0c;购物车是核心功能之一&#xff0c;需要兼顾数据一致性、用户体验和逻辑复杂度。 本文结合 Vue3 Pinia 技术栈&#xff0c;详细讲解如何实现一个高效且易用的购物车系统&#xff0c;重点剖析 添加购物车 和 头部购物车预览 的核心逻辑与实现细节。 一…

卡洛诗西餐厅,以“中式西餐”为核心战略

在餐饮市场的激烈竞争中&#xff0c;“本土化”是许多国际餐饮品牌难以跨越的鸿沟——要么因水土不服黯然退场&#xff0c;要么因过度妥协失去特色。然而&#xff0c;卡洛诗以“中式西餐”为核心战略&#xff0c;将西餐与国内饮食文化深度融合&#xff0c;不仅破解了西餐本土化…

28-29【动手学深度学习】批量归一化 + ResNet

1. 批量归一化 1.1 原理 当神经网络比较深的时候会发现&#xff1a;数据在下面&#xff0c;损失函数在上面&#xff0c;这样会出现什么问题&#xff1f; 正向传递的时候&#xff0c;数据是从下往上一步一步往上传递反向传递的时候&#xff0c;数据是从上面往下传递&#xff0…

【Linux网络】Http服务优化 - 增加请求后缀、状态码描述、重定向、自动跳转及注册多功能服务

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

AIGC(生成式AI)试用 32 -- AI做软件程序测试 3

总结之前的AI做程序测试过程&#xff0c;试图优化提问方式&#xff0c;整合完成的AI程序测试提问&#xff0c;探索更多可能的AI测试 AIGC&#xff08;生成式AI&#xff09;试用 30 -- AI做软件程序测试 1 AIGC&#xff08;生成式AI&#xff09;试用 31 -- AI做软件程序…

C语言实现迪杰斯特拉算法进行路径规划

使用C语言实现迪杰斯特拉算法进行路径规划 迪杰斯特拉算法是一种用于寻找加权图中最短路径的经典算法。它特别适合用于计算从一个起点到其他所有节点的最短路径&#xff0c;前提是图中的边权重为非负数。 一、迪杰斯特拉算法的基本原理 迪杰斯特拉算法的核心思想是“贪心法”…

引领印尼 Web3 变革:Mandala Chain 如何助力 1 亿用户迈向数字未来?

当前 Web3 的发展正处于关键转折点&#xff0c;行业亟需吸引新用户以推动 Web3 的真正大规模采用。然而&#xff0c;大规模采用面临着核心挑战&#xff1a;数据泄露风险、集中存储的安全漏洞、跨系统互操作性障碍&#xff0c;以及低效的服务访问等问题。如何才能真正突破这些瓶…

WebSocket是h5定义的,双向通信,节省资源,更好的及时通信

浏览器和服务器之间的通信更便利&#xff0c;比http的轮询等效率提高很多&#xff0c; WebSocket并不是权限的协议&#xff0c;而是利用http协议来建立连接 websocket必须由浏览器发起请求&#xff0c;协议是一个标准的http请求&#xff0c;格式如下 GET ws://example.com:3…

Kaamel白皮书:IoT设备安全隐私评估实践

1. IoT安全与隐私领域的现状与挑战 随着物联网技术的快速发展&#xff0c;IoT设备在全球范围内呈现爆发式增长。然而&#xff0c;IoT设备带来便捷的同时&#xff0c;也引发了严峻的安全与隐私问题。根据NSF&#xff08;美国国家科学基金会&#xff09;的研究表明&#xff0c;I…

php安装swoole扩展

PHP安装swoole扩展 Swoole官网 安装准备 安装前必须保证系统已经安装了下列软件 4.8 版本需要 PHP-7.2 或更高版本5.0 版本需要 PHP-8.0 或更高版本6.0 版本需要 PHP-8.1 或更高版本gcc-4.8 或更高版本makeautoconf 安装Swool扩展 安装官方文档安装后需要再php.ini中增加…

服务器传输数据存储数据建议 传输慢的原因

一、JSON存储的局限性 1. 性能瓶颈 全量读写&#xff1a;JSON文件通常需要整体加载到内存中才能操作&#xff0c;当数据量大时&#xff08;如几百MB&#xff09;&#xff0c;I/O延迟和内存占用会显著增加。 无索引机制&#xff1a;查找数据需要遍历所有条目&#xff08;时间复…

Android四大核心组件

目录 一、为什么需要四大组件&#xff1f; 二、Activity&#xff1a;看得见的界面 核心功能 生命周期图解 代码示例 三、Service&#xff1a;看不见的劳动者 两大类型 生命周期对比 注意陷阱 四、BroadcastReceiver&#xff1a;消息传递专员 两种注册方式 广播类型 …

「Mac畅玩AIGC与多模态01」架构篇01 - 展示层到硬件层的架构总览

一、概述 AIGC&#xff08;AI Generated Content&#xff09;系统由多个结构层级组成&#xff0c;自上而下涵盖交互界面、API 通信、模型推理、计算框架、底层驱动与硬件支持。本篇梳理 AIGC 应用的六层体系结构&#xff0c;明确各组件在系统中的职责与上下游关系&#xff0c;…

[MERN 项目实战] MERN Multi-Vendor 电商平台开发笔记(v2.0 从 bug 到结构优化的工程记录)

[MERN 项目实战] MERN Multi-Vendor 电商平台开发笔记&#xff08;v2.0 从 bug 到结构优化的工程记录&#xff09; 其实之前没想着这么快就能把 2.0 的笔记写出来的&#xff0c;之前的预期是&#xff0c;下一个阶段会一直维持到将 MERN 项目写完&#xff0c;毕竟后期很多东西都…