[LeetCode算法笔记]Find K Pairs with Smallest Sums与优先队列

2024-04-19 15:48

本文主要是介绍[LeetCode算法笔记]Find K Pairs with Smallest Sums与优先队列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

LeetCode第373题 Find K Pairs with Smallest Sums是一道中等难度的题
题面挺简单的:
给定两组升序排列的整形(int)数组,从中分别挑选k对和最小的数对(pair)
意思就是从两个数组中分别挑选一个数,组成一个数队,使两个数的和最小
例子:
输入:nums1:[1,6,7,11],nums2:[1,2,6,9],k=4
输出:[[1,1],[1,2],[6,1][1,6]]
这个问题在于如何进行有效的和比较。
暴力的方法就是先计算所有对的和,然后再进行排序。
而优化在于如何利用数组本身已经升序排列的前提,从而减少所需要的排序。

一、利用priority_queue优先队列的解法
C++的解法主要是利用到了priority_queue优先队列:
priority_queue最简单的用法:priority_queue<int>
有点类似于set,会自动将插入队列的值按照优先级大小排序,默认是从大到小。
这题的解法可以采用更经典用法:
priority_queue <TYPE, vector<TYPE>, greater<TYPE> >: 这里的TYPE指各种类型数据,TYPE表示数据类型,vector<TYPE>表示存储数据类型的向量,greater<>表示进行优先级比较的函数,greater指从大到小,less指从小到大
例如:priority_queue <int, vector<int>, greater<int> >: 指的是一个按值从大到小排序的int类型向量。
priority_queue优先队列,也就是原来我们学过的堆,按照自己定义的优先级出队时。默认情况下底层是以Vector实现的heap。既然是队列,也就只有入队、出队、判空、大小的操作,并不具备查找功能。其常用成员函数:
empty() 如果优先队列为空,则返回真
pop() 删除第一个元素
push() 加入一个元素
size() 返回优先队列中拥有的元素的个数
top() 返回优先队列中有最高优先级的元素
那么在C++中有了这样一个容器,我们可以将两数组中数的序号构成一对键值,而比较函数设置两数和的
class Solution {
public:vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {vector<pair<int,int>> res; // record resultif(nums1.size()==0||nums2.size()==0||k<=0)return res;auto cmp = [&nums1,&nums2](pair<int,int> a,pair<int,int> b){return nums1[a.first]+nums2[a.second]>=nums1[b.first]+nums2[b.second];};priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(cmp)> pq(cmp);pq.push(make_pair(0,0)); // the first int cnk=0;while(cnk<k){pair<int,int> t=pq.top();pq.pop();res.push_back(make_pair(nums1[t.first],nums2[t.second]));if(t.first+1<nums1.size())pq.push(make_pair(t.first+1,t.second));if(t.first==0 && (t.second+1<nums2.size()))pq.push(make_pair(t.first,t.second+1));if(t.second+1>=nums2.size()&&t.first+1>=nums1.size())break;cnk++;}return res;}
};



二、直接的算法
这个算法可以通过C语言来实现,不过LeetCode这道题的C语言版本的接口,我完全搞不清,所以就选择用C++来解决
这个算法的重点在于维持一个位置数组,这个数组保存数组1的某数搜索数组2的位置。
class Solution {
public:vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {vector<pair<int,int>> res;vector<int> pos(nums1.size()); // record the search pos of each num of nums1if(nums1.size()==0||nums2.size()==0||k==0)return res;int cnk=0;  // record push_back numwhile(cnk<k){int si=-1; // the search posint minsum=INT_MAX; // the min sumfor(int i=0;i<nums1.size();i++){if(nums1[i]+nums2[pos[i]]<minsum&&pos[i]<nums2.size()){minsum=nums1[i]+nums2[pos[i]];si=i;}}if(si==-1)break;res.push_back(make_pair(nums1[si],nums2[pos[si]]));pos[si]++;cnk++;}return res;            }
};



三、Python版本
Python里有一个heapq结构,类似于前面C++的优先队列,这个方法同前面也很类似。
def kSmallestPairs(self, nums1, nums2, k):queue = []def push(i, j):if i < len(nums1) and j < len(nums2):heapq.heappush(queue, [nums1[i] + nums2[j], i, j])push(0, 0)pairs = []while queue and len(pairs) < k:_, i, j = heapq.heappop(queue)pairs.append([nums1[i], nums2[j]])push(i, j + 1)if j == 0:push(i + 1, 0)return pairs


这篇关于[LeetCode算法笔记]Find K Pairs with Smallest Sums与优先队列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/917971

相关文章

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

Linux find 命令完全指南及核心用法

《Linuxfind命令完全指南及核心用法》find是Linux系统最强大的文件搜索工具,支持嵌套遍历、条件筛选、执行动作,下面给大家介绍Linuxfind命令完全指南,感兴趣的朋友一起看看吧... 目录一、基础搜索模式1. 按文件名搜索(精确/模糊匹配)2. 排除指定目录/文件二、根据文件类型筛选三、时间

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

Spring Boot整合消息队列RabbitMQ的实现示例

《SpringBoot整合消息队列RabbitMQ的实现示例》本文主要介绍了SpringBoot整合消息队列RabbitMQ的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录RabbitMQ 简介与安装1. RabbitMQ 简介2. RabbitMQ 安装Spring

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

Redis延迟队列的实现示例

《Redis延迟队列的实现示例》Redis延迟队列是一种使用Redis实现的消息队列,本文主要介绍了Redis延迟队列的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、什么是 Redis 延迟队列二、实现原理三、Java 代码示例四、注意事项五、使用 Redi