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

[特殊字符] 数组中的递增三元组:O(n) 时间高效查找,面试必考!

给定一个整数数组arr[],长度为 n,我们需要找出三个元素a[i] < a[j] < a[k]且下标i < j < k。要求时间复杂度为 O(n)。如果存在多个这样的三元组,输出任意一个即可。

示例:

  • 输入:arr[] = [12, 11, 10, 5, 6, 2, 30],输出:5, 6, 30(因为 5 < 6 < 30,且在数组中保持顺序)
  • 输入:arr[] = [1, 2, 3, 4],输出:1, 2, 3
  • 输入:arr[] = [4, 3, 2, 1],输出:No such triplet exists

目录

  • 朴素方法 - O(n) 时间,O(n) 空间
  • 期望方法 - O(n) 时间,O(1) 空间

朴素方法 - O(n) 时间,O(n) 空间

核心思想:找到一个元素,它在数组左边有比它小的元素,右边有比它大的元素。

  1. 创建辅助数组smaller[0..n-1]smaller[i]存储左侧比arr[i]小的元素的索引,如果没有则为 -1。
  2. 创建辅助数组greater[0..n-1]greater[i]存储右侧比arr[i]大的元素的索引,如果没有则为 -1。
  3. 最后遍历smaller[]greater[],找到索引i使得smaller[i] != -1greater[i] != -1

C++ 实现

#include<iostream>#include<vector>usingnamespacestd;vector<int>find3Numbers(vector<int>&arr){intn=arr.size();vector<int>smaller(n,-1);intmin=0;for(inti=1;i<n;i++){if(arr[i]<=arr[min])min=i;elsesmaller[i]=min;}vector<int>greater(n,-1);intmax=n-1;for(inti=n-2;i>=0;i--){if(arr[i]>=arr[max])max=i;elsegreater[i]=max;}for(inti=0;i<n;i++){if(smaller[i]!=-1&&greater[i]!=-1)return{arr[smaller[i]],arr[i],arr[greater[i]]};}return{};}intmain(){vector<int>arr={12,11,10,5,6,2,30};vector<int>res=find3Numbers(arr);for(intx:res)cout<<x<<" ";return0;}

Java 实现

importjava.util.*;classGfG{staticList<Integer>find3Numbers(int[]arr){intn=arr.length;int[]smaller=newint[n];Arrays.fill(smaller,-1);intmin=0;for(inti=1;i<n;i++){if(arr[i]<=arr[min])min=i;elsesmaller[i]=min;}int[]greater=newint[n];Arrays.fill(greater,-1);intmax=n-1;for(inti=n-2;i>=0;i--){if(arr[i]>=arr[max])max=i;elsegreater[i]=max;}for(inti=0;i<n;i++){if(smaller[i]!=-1&&greater[i]!=-1)returnArrays.asList(arr[smaller[i]],arr[i],arr[greater[i]]);}returnnewArrayList<>();}publicstaticvoidmain(String[]args){int[]arr={12,11,10,5,6,2,30};List<Integer>res=find3Numbers(arr);for(intx:res)System.out.print(x+" ");}}

Python 实现

deffind3Numbers(arr):n=len(arr)smaller=[-1]*n min_idx=0foriinrange(1,n):ifarr[i]<=arr[min_idx]:min_idx=ielse:smaller[i]=min_idx greater=[-1]*n max_idx=n-1foriinrange(n-2,-1,-1):ifarr[i]>=arr[max_idx]:max_idx=ielse:greater[i]=max_idxforiinrange(n):ifsmaller[i]!=-1andgreater[i]!=-1:return[arr[smaller[i]],arr[i],arr[greater[i]]]return[]arr=[12,11,10,5,6,2,30]res=find3Numbers(arr)forxinres:print(x,end=" ")

C# 实现

usingSystem;usingSystem.Collections.Generic;classGfG{staticList<int>find3Numbers(int[]arr){intn=arr.Length;int[]smaller=newint[n];for(inti=0;i<n;i++)smaller[i]=-1;intmin=0;for(inti=1;i<n;i++){if(arr[i]<=arr[min])min=i;elsesmaller[i]=min;}int[]greater=newint[n];for(inti=0;i<n;i++)greater[i]=-1;intmax=n-1;for(inti=n-2;i>=0;i--){if(arr[i]>=arr[max])max=i;elsegreater[i]=max;}for(inti=0;i<n;i++){if(smaller[i]!=-1&&greater[i]!=-1)returnnewList<int>{arr[smaller[i]],arr[i],arr[greater[i]]};}returnnewList<int>();}staticvoidMain(){int[]arr={12,11,10,5,6,2,30};List<int>res=find3Numbers(arr);foreach(intxinres)Console.Write(x+" ");}}

说到数组的递增三元组,刚刷完这道题是不是觉得O(n)的指针技巧很巧妙?但光靠脑补指针移动,很多同学面试时还是容易卡住。这里安利一个宝藏网站——图码,它提供了60多种数据结构和算法的交互式动画可视化。

你可以直接把这道题的代码贴进去,或者自定义数组数据,看指针如何一步步移动。对于正在准备408考研数据结构期末考试的同学,它还能上传C/C++/Java/Python代码进行可视化解析,甚至7×24小时选中代码就能问AI。
想彻底吃透这类面试必考题?赶紧去图码体验一下,让抽象的逻辑动起来。
图码-数据结构与算法交互式可视化平台
访问网站:https://totuma.cn

JavaScript 实现

functionfind3Numbers(arr){constn=arr.length;constsmaller=newArray(n).fill(-1);letmin=0;for(leti=1;i<n;i++){if(arr[i]<=arr[min])min=i;elsesmaller[i]=min;}constgreater=newArray(n).fill(-1);letmax=n-1;for(leti=n-2;i>=0;i--){if(arr[i]>=arr[max])max=i;elsegreater[i]=max;}for(leti=0;i<n;i++){if(smaller[i]!==-1&&greater[i]!==-1)return[arr[smaller[i]],arr[i],arr[greater[i]]];}return[];}constarr=[12,11,10,5,6,2,30];constres=find3Numbers(arr);for(constxofres){console.log(x+" ");}

输出:5 6 30


期望方法 - O(n) 时间,O(1) 空间

思路:先找到两个元素arr[i] < arr[j]i < j,然后在后续遍历中找arr[k] > arr[j]。我们可以在一次遍历中完成:

C++ 实现

#include<iostream>#include<vector>#include<climits>usingnamespacestd;vector<int>find3Numbers(vector<int>&arr){intn=arr.size();if(n<3)return{};intfirst=INT_MAX,second=INT_MAX,prevFirst=INT_MAX;for(inti=0;i<n;i++){intx=arr[i];if(x<=first){first=x;}elseif(x<=second){second=x;prevFirst=first;}else{return{prevFirst,second,x};}}return{};}intmain(){vector<int>arr={12,11,10,5,6,2,30};vector<int>res=find3Numbers(arr);for(intx:res)cout<<x<<" ";return0;}

Java 实现

importjava.util.*;classGfG{staticList<Integer>find3Numbers(int[]arr){intn=arr.length;if(n<3)returnnewArrayList<>();intfirst=Integer.MAX_VALUE;intsecond=Integer.MAX_VALUE;intprevFirst=Integer.MAX_VALUE;for(inti=0;i<n;i++){intx=arr[i];if(x<=first){first=x;}elseif(x<=second){second=x;prevFirst=first;}else{returnArrays.asList(prevFirst,second,x);}}returnnewArrayList<>();}publicstaticvoidmain(String[]args){int[]arr={12,11,10,5,6,2,30};List<Integer>res=find3Numbers(arr);for(intx:res)System.out.print(x+" ");}}

Python 实现

deffind3Numbers(arr):n=len(arr)ifn<3:return[]first=float('inf')second=float('inf')prevFirst=float('inf')forxinarr:ifx<=first:first=xelifx<=second:second=x prevFirst=firstelse:return[prevFirst,second,x]return[]arr=[12,11,10,5,6,2,30]res=find3Numbers(arr)forxinres:print(x,end=" ")

C# 实现

usingSystem;usingSystem.Collections.Generic;classGfG{staticList<int>find3Numbers(int[]arr){intn=arr.Length;if(n<3)returnnewList<int>();intfirst=int.MaxValue;intsecond=int.MaxValue;intprevFirst=int.MaxValue;for(inti=0;i<n;i++){intx=arr[i];if(x<=first){first=x;}elseif(x<=second){second=x;prevFirst=first;}else{returnnewList<int>{prevFirst,second,x};}}returnnewList<int>();}staticvoidMain(){int[]arr={12,11,10,5,6,2,30};List<int>res=find3Numbers(arr);foreach(intxinres)Console.Write(x+" ");}}

JavaScript 实现

functionfind3Numbers(arr){constn=arr.length;if(n<3)return[];letfirst=Number.MAX_VALUE;letsecond=Number.MAX_VALUE;letprevFirst=Number.MAX_VALUE;for(leti=0;i<n;i++){letx=arr[i];if(x<=first){first=x;}elseif(x<=second){second=x;prevFirst=first;}else{return[prevFirst,second,x];}}return[];}constarr=[12,11,10,5,6,2,30];constres=find3Numbers(arr);console.log(res.join(" "));

输出:5 6 30


总结

两种方法都能高效解决问题,但期望方法更优,适合面试中展示优化能力。

希望这篇博客能帮你掌握递增三元组的查找技巧!如果你有其他解法,欢迎留言讨论~ 🚀

http://www.jsqmd.com/news/774938/

相关文章:

  • “灵语星火”第二阶段团队记录(二)
  • 给Claude Code装个仪表盘 Claude HUD保姆级教程命令行也能直观可控
  • 告别纯寄存器:用STC-ISP工具图形化配置STC8H的PWM,5分钟生成代码
  • CUDA内核优化:从手工调优到AI驱动的自动化实践
  • 如何免费下载TIDAL高品质音乐:tidal-dl-ng完整使用教程
  • 明代裙装形制融入现代中国男装设计研究
  • python系列【仅供参考】:JS的解析与Js2Py使用
  • 通用网页内容提取器xungen:基于示例驱动的自动化数据抓取方案
  • 深度优化:2345清理王系统碎片清理功能详解
  • 在多模型聚合场景下体验 Taotoken 的路由与容灾能力
  • AI编程助手Awesome清单:开发者选型指南与实战评测
  • Godot XR Tools:加速VR/AR开发的模块化工具集与实战指南
  • 从零实现ChatGPT:深入解析Transformer架构与自注意力机制
  • 2026年最佳健身小程序推荐榜单,帮你解锁智能运动新体验
  • 前端响应式设计:最佳实践
  • mysql修改字段类型时如何避免中断业务_inplace与copy算法详解
  • YOLO26-seg分割优化:卷积魔改创新 | AAAI 2025 | 一种新颖的风车形卷积(PConv)符合微弱小目标分割的像素高斯空间分布,增强特征提取,显著增加接受野
  • API 越加机器越多?为什么很多系统还是慢得像“老牛拉车”?
  • 2026年4月评价高的AI无损测糖选果机制造商推荐,梨分选机/网纹瓜选果机,AI无损测糖选果机厂商哪家靠谱 - 品牌推荐师
  • 量子计算中的Gibbs态制备与离子阱实验
  • 【HackMyVM】Flute
  • 前端安全:XSS防御最佳实践
  • 下载安装 Temurin® JDK JDK 21 - LTS 速度很慢,有办法加速吗?
  • 【AISMM权威认证路径】:为什么头部科技公司已将AISMM Level 3设为CTO晋升硬门槛?
  • 为什么国内云厂商都在力推 OpenClaw(小龙虾)?
  • 内存级向量检索库memsearch:原理、实战与性能调优
  • python系列【仅供参考】:js2py模块--python中执行js
  • 如何在手机上3步完成Android内核刷入:Horizon Kernel Flasher终极指南
  • 使用gradient-cursor库为网页打造个性化渐变动态光标
  • 基于Alpine的paretOS:轻量级容器化操作系统的核心设计与实践