春招百题--堆--扩展篇--找出最小

news2024/11/25 23:51:25

其他类似题目:

373. 查找和最小的 K 对数字
378. 有序矩阵中第 K 小的元素
719. 找出第 K 小的数对距离
786. 第 K 个最小的素数分数
2040. 两个有序数组的第 K 小乘积
2386. 找出数组的第 K 大和

215. 数组中的第K个最大元素

不纠结直接sort排序解决。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int n=nums.size();
        sort(nums.begin(), nums.end());//从小到大排列
        return nums[n-k];
    }
};

//sort(nums,nums+n);//sort(s, s + 3);的形式应该只能用在数组,不能用在vector 

719. 找出第 K 小的数对距离

思路:

一开始想的是直接便利,求差值,然后找到第K个。

代码:但超出时间限制  时间复杂度0\left (n ^{2} \right )

class Solution {
public:
    int smallestDistancePair(vector<int>& nums, int k) {
        vector<int> distance;
        int dis;
        for(int i=0;i<nums.size();i++){
            for(int j=i+1;j<nums.size();j++){
                dis=abs(nums[i]-nums[j]);
                distance.push_back(dis);
            }
        }
        sort(distance.begin(),distance.end());
        return distance[k-1];
    }
};

超出时间限制                16 / 19 个通过的测试用例

改进一下: 

方法一:双指针+二分法

这个方法是将距离划分成一个有序序列:距离在(0,max(nums)-min(nums))之间。

这样我们找找出第 K 小的数对距离---》转换为找 距离 序列 里面第k小的元素。--》思考二分法

不同的是,我们这个距离序列需要动态计算,而不是事先求出来的。

为了将计算量减少,我们不防直接计算元素个数与k(个数)相比;而不是原先的  k值与 中间位置的数相比较。

元素个数计算方法:

class Solution {
public:
    int countPairs(const vector<int>& nums, int mid) {
        int count = 0;
        int n = nums.size();
        int j = 0;
        for (int i = 0; i < n; ++i) {
            while (j < n && nums[j] - nums[i] <= mid) {
                ++j;
            }
            count += j - i - 1;
        }
        return count;
    }
    
    int smallestDistancePair(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        int n = nums.size(), left = 0, right = nums.back() - nums.front();
        while (left <= right) {
            int mid = left + (right - left) / 2;
            int cnt = countPairs(nums, mid);
            if (cnt >= k)
                right = mid - 1;
            else
                left = mid + 1;
        }
        return left;
    }
};

378. 有序矩阵中第 K 小的元素

方法一:暴力法

将二维数组存储到一维数组中,然后排序。

class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n=matrix.size();
        vector<int> ans;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++)
             ans.push_back(matrix[i][j]);
        }
        sort(ans.begin(),ans.end());
        return ans[k-1];
    }
};

时间复杂度:0\left ( n^{2} logn\right )空间复杂度:0\left ( n^{2} \right )

方法二:归并排序--》堆

由题目给出的性质可知,这个矩阵的每一行均为一个有序数组。问题即转化为从这 n 个有序数组中找第 k大的数,可以想到利用归并排序的做法,归并到第 k个数即可停止。

大体思路:

  • 首先,定义了一个结构体 Element,用于表示矩阵中的元素及其在矩阵中的位置。
  • 使用一个最小堆(由 priority_queue 实现),其中元素按照它们的值(val)从小到大排序。这个最小堆用于存储和排序所有可能成为第k小元素的候选。
  • 初始化时,将矩阵的第一列所有元素加入到最小堆中。这是因为矩阵是按行和按列都排序的,所以每行的第一个元素是该行的最小值,有可能是全局第k小的值。
  • 接下来,重复执行k-1次从最小堆中取出元素的操作。每次取出堆顶元素后,检查这个元素是否有右侧的相邻元素(即检查是否到达了其所在行的末尾),如果有,则将这个右侧的相邻元素加入到最小堆中。这保证了堆中始终保存着所有可能是第k小元素的候选。
  • 经过k-1次取出操作后,最小堆的堆顶元素就是第k小的元素,返回其值。
class Solution {
public:
    int kthSmallest(vector<vector<int>>& matrix, int k) {
        // 定义一个结构体,用来表示矩阵中的元素及其位置
        struct Element {
            int val; // 元素的值
            int x, y; // 元素在矩阵中的位置(行x,列y)
            Element(int val, int x, int y) : val(val), x(x), y(y) {}
        };

        // 优先队列的比较函数,用于构建最小堆
        auto cmp = [](const Element& a, const Element& b) {
            return a.val > b.val;
        };
        
        // 定义一个最小堆,用于存储Element结构体,其中元素按照val值从小到大排序
        priority_queue<Element, vector<Element>, decltype(cmp)> minHeap(cmp);
        
        int n = matrix.size(); // 矩阵的维度
        
        // 初始化堆,将矩阵的第一列元素全部加入堆中
        for (int i = 0; i < n; i++) {
            minHeap.emplace(matrix[i][0], i, 0);
        }
        
        // 循环k-1次,每次从堆中取出最小的元素,并将该元素所在行的下一个元素加入堆中
        for (int i = 0; i < k - 1; i++) {
            Element cur = minHeap.top(); // 取出当前堆顶元素,即最小元素
            minHeap.pop(); // 从堆中移除该元素
            
            if (cur.y != n - 1) { // 如果当前元素不是所在行的最后一个元素
                // 将当前元素所在行的下一个元素加入堆中
                minHeap.emplace(matrix[cur.x][cur.y + 1], cur.x, cur.y + 1);
            }
        }
        
        // 循环结束后,堆顶元素即为第k小的元素
        return minHeap.top().val;
    }
};
方法三:二分法

类似上一道题目:

  • 初始化左边界 left 为矩阵中的最小元素,右边界 right 为矩阵中的最大元素。
  • 在 while 循环中,通过二分法不断调整 left 和 right,直到它们相等。
  • 在每次循环中,计算中间值 mid,然后统计矩阵中不大于 mid 的元素个数 count
  • 如果 count 小于 k,说明第 k 小的元素在右半部分,将 left 更新为 mid + 1
  • 否则,第 k 小的元素在左半部分,将 right 更新为 mid
  • 当 left 和 right 收敛时,返回 left 或 right 即可,它们的值相等且为第 k 小的元素。

这种方法的时间复杂度为O(nlog(max-min)),其中n为矩阵的维度,max和min分别为矩阵中的最大值和最小值。

class Solution {
public:
    int Count(vector<vector<int>>& matrix, int mid) {
        int count = 0;
        int n=matrix.size();
        int j = n - 1;
        for (int i = 0; i < n; ++i) {
            while (j >= 0 && matrix[i][j] > mid) {
                j--;
            }
            count += (j + 1);
        }
        return count;
    }
        int kthSmallest(vector<vector<int>>& matrix, int k) {
        int n = matrix.size();
        int left = matrix[0][0]; // 左边界为矩阵中最小的元素
        int right = matrix[n - 1][n - 1]; // 右边界为矩阵中最大的元素

        while (left < right) {
            int mid = left + (right - left) / 2;
            int count = Count(matrix, mid); // 统计不大于mid的元素个数
            // 如果count小于k,说明第k小的元素在右半部分
            if (count < k) {
                left = mid + 1;
            } else { // 否则在左半部分
                right = mid;
            }
        }
        // left和right收敛时,即为第k小的元素
        return left;
    }
};

786. 第 K 个最小的质数分数

题目:

给你一个按递增顺序排序的数组 arr 和一个整数 k 。数组 arr 由 1 和若干 质数 组成,且其中所有整数互不相同。

对于每对满足 0 <= i < j < arr.length 的 i 和 j ,可以得到分数 arr[i] / arr[j] 。

那么第 k 个最小的分数是多少呢?  以长度为 2 的整数数组返回你的答案, 这里 answer[0] == arr[i] 且 answer[1] == arr[j] 。

思路:

方法一:二分法

class Solution {
public:
    
    vector<int> kthSmallestPrimeFraction(vector<int>& arr, int k) {
        int n=arr.size();
        double left=0;double right=1;

        while(1){
            double mid=left+(right-left)/2;
            int i=-1,count=0;
            int x=arr[0],y=arr[n-1];

            for(int j=1;j<n;j++){
                while((double)arr[i+1]/arr[j]<mid){
                    ++i;
                    if(arr[i]*y>arr[j]*x){
                        x=arr[i];
                        y=arr[j];
                    }
                }
                count+=i+1;
            }


            if(count==k) return{x,y};
            if(count<k) left=mid;
            else right=mid;
        }
    }
};

方法三:优先队列:

使用「扫描点对」+「优先队列(堆)」的做法,使用二元组 (arr[i],arr[j]) 进行存储,构建大小为 k的大根堆。

根据「堆内元素多少」和「当前计算值与堆顶元素的大小关系」决定入堆行为:

  • 若堆内元素不足 k个,直接将当前二元组进行入堆;
  • 若堆内元素已达 k个,根据「当前计算值 arr[i]/arr[j] 与堆顶元素 peek[0]\peek[1]的大小关系」进行分情况讨论:
  •         如果当前计算值比堆顶元素大,那么当前元素不可能是第 k 小的值,直接丢弃;
  •         如果当前计算值比堆顶元素小,那么堆顶元素不可能是第 k小的值,使用当前计算值置换掉堆顶元素。

构建比较关系函数:

// 自定义比较函数,用于维护最小堆
        auto compare = [](const vector<int>& a, const vector<int>& b) {
            // 计算分数值,转换为 double 类型进行比较
            double fracA = static_cast<double>(a[0]) / a[1];
            double fracB = static_cast<double>(b[0]) / b[1];
            return fracA < fracB;
        };

class Solution {
public:
    vector<int> kthSmallestPrimeFraction(vector<int>& arr, int k) {
        int n = arr.size();
        
        // 自定义比较函数,用于维护最小堆
        auto compare = [](const vector<int>& a, const vector<int>& b) {
            // 计算分数值,转换为 double 类型进行比较
            double fracA = static_cast<double>(a[0]) / a[1];
            double fracB = static_cast<double>(b[0]) / b[1];
            return fracA < fracB;
        };
        
        // 声明优先队列,使用自定义比较函数构造最小堆
        priority_queue<vector<int>, vector<vector<int>>, decltype(compare)> q(compare);
        
        // 遍历数组 arr,找到前 k 个最小的质数分数
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                // 计算当前分数值
                double t = static_cast<double>(arr[i]) / arr[j];
                // 如果队列大小小于 k 或者当前分数比堆顶元素小,则入堆
                if (q.size() < k || static_cast<double>(q.top()[0]) / q.top()[1] > t) {
                    if (q.size() == k) q.pop(); // 维护堆大小为 k
                    q.push({arr[i], arr[j]}); // 入堆当前分数对
                }
            }
        }
        
        return q.top(); // 返回堆顶元素,即第 k 小的质数分数
    }
};

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

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

相关文章

SpringBoot项目接入Nacos注册中心

前置 已经安装好Nacos服务&#xff0c;并且该项目所在服务器可以访问到 可以参考下&#xff1a; windows环境安装Nacos单机版-CSDN博客 Centos7安装Nacos单机版-CSDN博客 1. POM文件引入依赖 注意&#xff0c;父工程已经引入spring cloud依赖管理的情况下不用添加版本号 …

基于opencv的视觉巡线实现

前言 这段时间在和学弟打软件杯的比赛&#xff0c;有项任务就是机器人的视觉巡线&#xff0c;这虽然不是什么稀奇的事情&#xff0c;但是对于一开始不了解视觉的我来说可以说是很懵了&#xff0c;所以现在就想着和大家分享一下&#xff0c;来看看是如何基于opencv来实现巡线的…

天猫商品详情数据接口(Tmall.item_get)天猫搜索商品列表接口

天猫商品详情数据接口&#xff08;Tmall.item_get&#xff09;是天猫开放平台提供的一种API接口&#xff0c;旨在帮助开发者获取天猫平台上的商品详情信息。通过调用这个接口&#xff0c;开发者可以获取包括商品ID、标题、价格、库存量、图片等在内的详细数据&#xff0c;从而更…

由elemnent-ui模拟一个全选、反选效果想到的购物车逻辑案例

本文参考 https://blog.csdn.net/sumimg/article/details/137508302?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22137508302%22%2C%22source%22%3A%22sumimg%22%7D 我遇到的问题 点击店铺二级的时候&#xff0c;checkedCiti…

HNUST湖南科技大学嵌入式开发板使用-2024

目录 1.需要准备的软件(版本必须相同)꒰ঌ( ⌯ ⌯)໒꒱ 2.下载链接地址⌯▾⌯ 3.软件安装教程 4.安装好了&#xff0c;正常情况会是什么样子呢&#xff1f;(๑•̌.•๑) 4.1.拆入第一个接口(串口com接口是用来上传代码的ฅ˙Ⱉ˙ฅ) 4.2.拆入第三个接口&#xff08;SWD Jlink口…

鸿蒙应用开发之富文本(RichText)组件

前面学习了评分组件,现在来学习富文本组件,这个组件用来表示复杂的文本,把文本显示得更加有特色,比如网页一样显示。这种显示会比较复杂,所以应用的场合就会少一点。不过富文本显示最多的,就是即时通讯软件了,比如显示图片与文本,以及一些特殊的字符。 比如显示如下面的…

Unity Standalone File Browser,Unity打开文件选择器

Unity Standalone File Browser&#xff0c;Unity打开文件选择器 下载地址&#xff1a;GitHub链接&#xff1a; https://github.com/gkngkc/UnityStandaloneFileBrowser简单的示例代码 using SFB; using System; using System.IO; using UnityEngine; using UnityEngine.UI;…

【自然语言处理八-transformer实现翻译任务-一(输入)】

自然语言处理八-transformer实现翻译任务-一&#xff08;输入&#xff09; transformer架构数据处理部分模型的输入数据(图中inputs outputs outputs_probilities对应的label)以处理英中翻译数据集为例的代码 positional encoding 位置嵌入代码 鉴于transfomer的重要性&#xf…

Ja-netfilter(idea激活码破解原理)分析

Ja-netfilter&#xff08;idea破解&#xff09;分析 简介 ja-netfilter是一款可以破解jetbrainsIDE系列的javaagent jar 包。 原理简介 通过javaagent创造修改字节码的时机。通过asm修改相关类&#xff0c;达到hook特定方法的作用。主要依赖power&#xff08;rsa方法hook&a…

【Java】Set集合的基本使用

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 一、HashSet集合 1.HashSet集合的特点 2.HashSet常用方法 ①&#xff1a;add(Object o)&#xff1a;向Set集合中添加元素&#xff0c;不允许添加重复数据。 ②&#xff1a;size()&#xff1a;返回Set集合中的元素个数…

NASA数据集——亚洲夏季季风化学与气候影响项目超高灵敏度气溶胶光谱(UHSAS)数据

ACCLIP_Aerosol_AircraftInSitu_WB57_Data 简介 ACCLIP_Aerosol_AircraftInSitu_WB57_Data 是亚洲夏季季风化学与气候影响项目&#xff08;ACCLIP&#xff09;期间收集的原地气溶胶数据。本数据集收录了来自下一代激光质谱仪&#xff08;PALMS-NG&#xff09;、单颗粒烟尘光度…

0101tomcat部署war访问mysql失败-容器间通信-docker项目部署

文章目录 一、简介二、部署1、mysql数据迁移2、docker部署redis3、docker部署tomcat并运行war包 三、报错四、解决1 分析2 解决 结语 一、简介 最近参与开发一个项目&#xff0c;其中一部分系统需要迁移。从阿里云迁移到实体服务器&#xff0c;使用docker部署。系统使用Java语…

RAG进阶之通用文档处理:从RAGFlow、TextMonkey到mPLUG-DocOwl 1.5

前言 我司RAG项目组每个月都会接到一些B端客户的项目需求&#xff0c;做的多了&#xff0c;会发现很多需求是大同小异的&#xff0c;所以我们准备做一个通用的产品&#xff0c;特别是对通用文档的处理 而在此之前&#xff0c;我们则想先学习一下目前市面上各种优秀的解决方法…

IIS服务器更换即将过期的SSL证书

公司IIS服务器证书快要过期&#xff0c;替换证书的步骤&#xff1a; Winr输入mstsc命令&#xff0c;显示远程登录&#xff1b;输入服务器IP以及密码&#xff0c;进行远程登陆登陆IIS服务器&#xff0c;winr输入inetmgr命令显示IIS操控器&#xff1b;选择服务器证书--点击服务器…

成为摄影拍照高手,摄影技术进阶秘籍

一、资料前言 本套摄影高手资料&#xff0c;大小2.02G&#xff0c;共有57个文件。 二、资料目录 DSLR数码单反摄影圣经.pdf photoshop超细的人像后期磨皮及专业美化.docx “失传”的人像拍摄绝技.doc 白加黑减.怎样应用曝光补偿.pdf 标准镜头秘笈&#xff1a;标准镜如何…

快速寻找可以构建出网通信隧道的计算机

点击星标&#xff0c;即时接收最新推文 本文选自《内网安全攻防&#xff1a;红队之路》 扫描二维码五折购书 为加强内网的安全防范&#xff0c;安全管理员往往会限制内网计算机访问互联网&#xff0c;当然不同机构的限制策略是不一样的&#xff0c;有的完全阻断了内网计算机访问…

langchain LCEL,prompt模块,outputparse输出模块

目录 基本代码 prompt模块 prompt模版控制长度 outputparse格式化输出 并行使用调用链 LangChain表达式语言&#xff0c;或者LCEL&#xff0c;是一种声明式的方式&#xff0c;可以轻松地将链条组合在一起 langchian 可以使用 通义千问&#xff0c;我们用通义千问&#x…

openkylin系统通过网线连接ubuntukylin系统上网攻略

openkylin系统通过网线连接ubuntukylin系统上网攻略 主机1&#xff1a;x64 amd &#xff0c;系统&#xff1a;ubuntukylin 22.04 &#xff0c;状态&#xff1a;通过wifi连接热点进行上网&#xff0c;并共享网络。 主机2&#xff1a;x64 intel &#xff0c;系统&#xff1a;ope…

阿里一面:如何将重复性比较高的 String 类型的地址信息从 20GB 降到几百兆?...

这次应该是互联网及软件行业的第三次寒潮&#xff0c;大家在寒潮中一定要继续保持学习&#xff0c;寒潮挺过去以后还是会迎来新的发展机遇。 有粉丝去阿里面试&#xff0c;跟码哥分享了其中一题面试问题「如何将重复性比较高的 String 类型的地址信息从 20GB 降到几百兆&#x…

linux创建文件、linux创建文件的几种方式、touch、echo、cat、vi、vim

文章目录 一、创建文件1.1、touch1.2、echo1.3、cat1.4、vi或vim 一、创建文件 1.1、touch touch命令&#xff1a;用于创建一个新的空文件或者更新已存在文件的访问和修改时间。 &#xff08;1&#xff09;如果目标文件不存在&#xff0c;则新建一个文件 touch demo.txt&am…