news 2026/1/3 14:54:44

D.二分查找-进阶——3488. 距离最小相等元素查询

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
D.二分查找-进阶——3488. 距离最小相等元素查询

题目链接:3488. 距离最小相等元素查询(中等)

算法原理:

解法一:哈希表(会超时)

时间复杂度O(M×N)

哈希表存<值,此值出现的下标集合>

遍历queries,取到对应在nums中的值,如果没有取到本身这个下标,就取环形数组中距离此值最近的相同值的距离存进结果链表中

注:取环形链表的下标间的距离可以用Math.min(Math.abs(tmp-x), n-Math.abs(tmp-x))

解法二:二分查找

124ms击败74.20%

时间复杂度O(NLogN)

①预处理 —— 存储每个元素的所有原数组索引
遍历原数组nums,哈希表存<值,该值在原数组中的所有索引列表p>
特性:天然升序,为后续二分查找提供基础
②处理每个查询下标i
对每个查询的原数组下标i,依次执行以下操作:
特殊情况:p的长度为1时说明只有一个元素,直接添加-1
二分查找:i一定存在p中,所以一定能找到,最左端点和最右端点模型均可
prev = (left - 1 + k) % k:处理left=0时,前一个下标为p的最后一个下标(循环逻辑)
next = (left + 1) % k:处理left=k-1时,后一个下标为p的第一个下标(循环逻辑)
计算原数组环形最短距离:
结合原数组的环形特性,取「直接距离」和「原数组长度n - 直接距离」的最小值(即环形最短距离),得到disprev和disnext
结果存储:取disprev和disnext的最小值,添加到结果列表中
③返回结果
遍历完所有查询后,返回结果列表ret

答疑

Q1:为什么p的下标可以用取模?

因为p记录的是nums中数的下标,而nums是环形数组

Q2:为什么 nums 的环形距离不能直接用取模?

取模只能确定下标,而解决不了有距离的路径最短的问题

Java代码:

class Solution { public List<Integer> solveQueries(int[] nums, int[] queries) { Map<Integer,List<Integer>> hash=new HashMap<>(); int n=nums.length; List<Integer> ret=new ArrayList<>(); for(int i=0;i<n;i++) hash.computeIfAbsent(nums[i],k->new ArrayList<>()).add(i); for(int x:queries){ int t=nums[x]; int mins=0x3f3f3f3f; List<Integer> a=hash.get(t); for(int tmp:a) if(x-tmp!=0) mins=Math.min(mins,Math.min(Math.abs(tmp-x), n-Math.abs(tmp-x))); if(mins==0x3f3f3f3f) mins=-1; ret.add(mins); } return ret; } }
class Solution { public List<Integer> solveQueries(int[] nums, int[] queries) { Map<Integer,List<Integer>> hash=new HashMap<>(); int n=nums.length; List<Integer> ret=new ArrayList<>(); for(int i=0;i<n;i++) hash.computeIfAbsent(nums[i],k->new ArrayList<>()).add(i); for(int i:queries){ //i是nums的下标 List<Integer> p=hash.get(nums[i]); int k=p.size(); //这个元素只出现一次 if(k==1){ret.add(-1);continue;} //找到当前i在列表p中的位置 //由于当前索引一定在p中存在,所以用最左端点和最右端点的模型均可 int left=0,right=p.size()-1; while(left<right){ int mid=left+(right-left)/2; if(p.get(mid)<i) left=mid+1; else right=mid; } int prev=(left-1+k)%k; int next=(left+1)%k; //计算原数组索引的距离 int disprev = Math.min(Math.abs(i-p.get(prev)), n - Math.abs(i-p.get(prev))); // nums环形距离 int disnext = Math.min(Math.abs(i-p.get(next)), n - Math.abs(i-p.get(next))); // nums环形距离 ret.add(Math.min(disnext,disprev)); } return ret; } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/21 21:39:48

Vscode插件开发实战:让代码编辑器也能播放ACE-Step生成的专注音乐

VSCode 插件开发实战&#xff1a;让代码编辑器也能播放 ACE-Step 生成的专注音乐 在开发者日常编码中&#xff0c;背景音乐早已不是“可有可无”的点缀。很多人依赖 Lo-fi、白噪音或轻电子乐来屏蔽干扰、维持心流。但问题也随之而来——打开 Spotify 或 YouTube&#xff0c;切歌…

作者头像 李华
网站建设 2025/12/16 0:36:34

9、双信号模型在信号处理中的应用

双信号模型在信号处理中的应用 1. 引言 在信号处理领域,双信号模型(DSM)是一类重要的算法。其主要特点是在传统非线性回归信号模型中,将一维时间序列的采样或离散时间点进行非线性映射到再生核希尔伯特空间(RKHS),并利用核技巧,通过核函数比较序列中不同时间点来展开…

作者头像 李华
网站建设 2025/12/29 13:42:23

5分钟搞定跨平台标签打印:LPrint终极指南

5分钟搞定跨平台标签打印&#xff1a;LPrint终极指南 【免费下载链接】lprint A Label Printer Application 项目地址: https://gitcode.com/gh_mirrors/lp/lprint 还在为不同系统的标签打印机驱动而烦恼吗&#xff1f;LPrint是一款开源的标签打印应用程序&#xff0c;能…

作者头像 李华
网站建设 2025/12/16 0:36:15

13、核方法在聚类与异常检测中的应用

核方法在聚类与异常检测中的应用 在信号处理领域,许多问题都涉及识别能更好表示信号的子空间,而在数据中找到优质且具代表性的组或簇是解决这类问题的主要途径。核方法为解决这些问题提供了有效的手段,下面将详细介绍核方法在聚类、领域描述、子空间检测、异常变化检测以及…

作者头像 李华
网站建设 2025/12/16 0:35:00

什么是缓存穿透、缓存击穿和缓存雪崩?如何解决?

缓存三大杀手&#xff1a;穿透、击穿与雪崩的深度解析与防御策略 关键词 缓存穿透, 缓存击穿, 缓存雪崩, 分布式系统, 性能优化, 高并发, 缓存策略 摘要 在当今高并发、大数据量的分布式系统环境中&#xff0c;缓存技术已成为提升系统性能、减轻数据库负担的关键手段。然而…

作者头像 李华
网站建设 2025/12/16 0:34:41

Python⾼级语法(装饰器、⽣成器、上下⽂管理器等)

Python⾼级语法(装饰器、⽣成器、上下⽂管理器等) 文章目录 Python⾼级语法(装饰器、⽣成器、上下⽂管理器等) Python 高级语法详解 📚 目录概览 1. 装饰器 (Decorators) 1.1 装饰器本质 1.2 保留函数元信息 1.3 带参数的装饰器 1.4 类装饰器 1.5 常用装饰器实例 1.6 装饰…

作者头像 李华