当前位置: 首页 > web >正文

[算法][好题分享][第三大的数][最短无序子数组]

算法小练

第三大的数

leetcode 链接

问题找到数组中的第三的数,我的第一个思路还是topk问题,就是通过构建一个堆表示当前最大的几个数

时间复杂度 : n * log(k)

思路:

  1. 首先将数组的前k个数构建一个小根堆,然后如果新的数,大于堆顶,将堆顶删除,将这个数添加

  2. 如果没有,continue

class Solution {
public:int thirdMax(vector<int>& nums) {// 边界判断if(nums.size() == 2)return std::max(nums[0], nums[1]);else if(nums.size() == 1) return nums[0];std::priority_queue<int,std::vector<int>,std::greater<int>> pq;// 默认是小根堆for(int i = 0;i < 3;i++)pq.push(nums[i]);for(int i = 3;i < nums.size();i++){if(nums[i] > pq.top()) {pq.pop();pq.push(nums[i]);}}return pq.top();}
};

这是我第一次写的,显然出现了一个问题,就是审题不清晰,这道题还需要我们进行数据的去重,就是同样的数据不能计算两次。

解决方式就是通过hash表进行去重,但是这样可能造成o(n)的空间复杂度的浪费,这里我们不推荐

所以换一种思路

因为三很小,我们直接通过设计三个常量来进行表示

class Solution {
public:int thirdMax(vector<int>& nums) {long long firs = LONG_MIN, secon = LONG_MIN, thir = LONG_MIN;for(int i = 0;i < nums.size();i++){int x = nums[i];if(x > firs && x < secon)firs = x;else if(x > secon && x < thir){firs = secon;secon = x;}else if(x > thir){firs = secon;secon = thir;thir = x;}}//if(firs != LONG_MIN) return firs;else return std::max(secon, thir);}
};

最短无序连续数组, 经典

leetcode链接

在这里插入图片描述

我直接看到这道题目的一路就是将排好序的数组和这道题目直接对比,对比出的第一个不同的位置和最后一个不同位置的差 + 1就是答案

class Solution {
public:int findUnsortedSubarray(vector<int>& nums) {std::vector<int> copy_nums;std::copy(nums.begin(),nums.end(),std::back_inserter(copy_nums));std::sort(copy_nums.begin(), copy_nums.end());// 找到开始不同的位置for(auto e : copy_nums) std::cout << e << " ";std::cout << std::endl;int n = nums.size();int i = 0;for(i = 0;i < n;i++){if(copy_nums[i] != nums[i]) break;}// if(i == n) return 0; // 完全相同// 从后往前找int j = 0;for(j = n - 1;j >= i;j--)if(copy_nums[j] != nums[j]) break;return  j - i + 1;}
};

但是呢,他有希望你是否能够给出一个o(n)时间复杂度的算法,上面算法中利用了std::sort, 他的底层快速排序为n * log(n), 所以现在我们思考如何才能对其进行优化呢?

优化思路:

什么样的部分我们需要重拍,当前位置前面存在一个比我还大的数,比如[1 3 5 4]

4这个位置现任是错的,因为他的前面有一个5, 从左遍历可以帮助我们找到无序列表的最右端,对吧,

因为我们找到4是错的,但是不能判断5是错的,当我们再次从右向左进行遍历的时候,发现我的后面有

一个比我小的数,就把5找到了。

class Solution {
public:int findUnsortedSubarray(vector<int>& nums) {// 从左往右找找到右边界int Max = -INT32_MAX;int left_edge = 0, right_edge = 0;// 右边界for(int i = 0;i < nums.size();i++){if(Max > nums[i]) right_edge = i;else Max = nums[i];}//左边界int Min = INT32_MAX;for(int i = nums.size() - 1;i >= 0;i--){if(Min < nums[i]) left_edge = i;else Min = nums[i]; }return left_edge == right_edge ? 0 : right_edge - left_edge + 1;}
};

总结: 这道题目我们需要定位出矛盾,什么样的位置需要排列,某个位置存在大于我们的数, 或者某个位置后存在小于我们的数,都是矛盾,通过两次o(n)的循环找到矛盾即可。

http://www.xdnf.cn/news/13773.html

相关文章:

  • 小飞电视:智能电视与移动设备的娱乐新选择
  • Meta发布V-JEPA 2世界模型及物理推理新基准,推动AI在物理世界中的认知与规划能力
  • Python 标准库之 os 模块
  • Vue + element实现电子围栏功能, 根据省市区选择围栏, 自定义围栏 ,手动输入地名围栏, 保存围栏,清除围栏,加载围栏,批量检测标点是否在围栏内。
  • Chapter05-SSRF
  • Nodejs特训专栏-基础篇:1. Node.js环境搭建与项目初始化详细指南
  • Conda 安装 nbextensions详细教程
  • C++编程语言:标准库:STL容器(Bjarne Stroustrup)
  • 2025【证券从业】时间事件
  • CHI 总线协议及一致性总线相关的 NOC
  • c/c++ 汇编码中的.cfi 指令有什么用途?
  • (LeetCode 每日一题) 3423. 循环数组中相邻元素的最大差值 (数组)
  • Java面试避坑指南:牛客网最新高频考点+答案详解
  • Mac电脑-Office 2024 长期支持版 PPT、Excel、Word(Mac中文)
  • RabbitMQ实现异步消息监听机制
  • Makefile 学习笔记
  • 无外接物理显示器的Ubuntu系统的远程桌面连接(升级版)
  • C#学习第30天: 匹配模式
  • 大模型技术30讲-5-利用数据来减少过拟合现象
  • Next.js + Supabase = 快速开发 = 高速公路
  • 怎样下载某个SCI期刊的endnote style?答:直接去endnote官网搜索期刊名称并下载即可
  • JMeter + 命令行服务器端压测全流程详解
  • 风控系统中,要调用第三方服务获取信息,很慢,如何解决?
  • vue3项目移动端实现进度条可手动滑动控制进度和点击控制进度
  • Docker入门篇--从安装到使用
  • 【Linux手册】从「程序」到「进程」:计算机世界的运行机制
  • 智慧养老与数字健康:科技赋能老年生活,构建全方位养老体系
  • Redis核心数据结构详解与应用
  • arduino通过控制器,精准控制24V电动轮毂转动
  • 解锁Scrapy爬虫:从入门到实战的Python秘籍