每日一道leetcode(2026.04.16):距离最小相等元素查询

每日一道leetcode(2026.04.16):距离最小相等元素查询

  • [1. 题目](#1. 题目)
  • [2. 分析](#2. 分析)
  • [3. 代码实现](#3. 代码实现)

1. 题目

给你一个 环形 数组 nums 和一个数组 queries 。

对于每个查询 i ,你需要找到以下内容:

数组 nums 中下标 queriesi 处的元素与 任意 其他下标 j(满足 numsj == numsqueries\[i])之间的 最小 距离。如果不存在这样的下标 j,则该查询的结果为 -1 。 返回一个数组answer,其大小与 queries 相同,其中 answeri 表示查询i的结果。

示例 1:

输入: nums = 1,3,1,4,1,3,2, queries = 0,3,5

输出: 2,-1,3

解释:

查询 0:下标 queries0 = 0 处的元素为 nums0 = 1 。最近的相同值下标为 2,距离为 2。 查询 1:下标queries1 = 3 处的元素为 nums3 = 4 。不存在其他包含值 4 的下标,因此结果为 -1。 查询 2:下标queries2 = 5 处的元素为 nums5 = 3 。最近的相同值下标为 1,距离为 3(沿着循环路径:5 -> 6 -> 0 -> 1)。

示例 2:

输入: nums = 1,2,3,4, queries = 0,1,2,3

输出: -1,-1,-1,-1

解释:

数组 nums 中的每个值都是唯一的,因此没有下标与查询的元素值相同。所有查询的结果均为 -1。

提示:

1 <= queries.length <= nums.length <= 10e5

1 <= numsi <= 10e6

0 <= queriesi < nums.length

2. 分析

这道题能看到很多其它题型的影子,其实就是快速找到指定下标位置元素值最相近的元素位置。这里我一开始是通过一个数组nums的全遍历,将所有出现的数值放到一个Map中,key为对应的数值,value为出现的所有下标List,这样再确认最小距离的时候,只需要找到指定的下标,然后比较下标前一个和后一个的距离,取较小值即可。

需要稍微注意的是,nums数组表述为环形数组,即下标0和length-1是相连的。

按照这个思路实现逻辑后,通过了绝大多数的测试用例,但倒在了下面这个精心定制的用例上。

在这个用例中,数组nums由特别多是1组成,queries又是分布特别广泛的大数,这样在定位对应的下标时就会执行特别多次循环。

出于这种相同Key值对应List长度超长的情况,我试着使用双向指针的方式去获取最短的距离,所以就基于数组长度以64为间隔,小的范畴仍沿用List中的遍历,大的范畴使用双向指针。

3. 代码实现

java 复制代码
class Solution {
    public List<Integer> solveQueries(int[] nums, int[] queries) {
        Map<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (!map.containsKey(nums[i])) {
                map.put(nums[i], new ArrayList<>());
            }
            List<Integer> list = map.get(nums[i]);
            if (list.size() > 64) {
                continue;
            }
            list.add(i);
        }
        int[] res = new int[queries.length];
        for (int i = 0; i < queries.length; i++) {
            int index = queries[i];
            int query = nums[index];
            List<Integer> list = map.get(query);
            if (list == null || list.size() <= 1) {
                res[i] = -1;
                continue;
            }

            if (list.size() > 64) {
                // 使用双向指针进行遍历
                int left = index;
                int right = index;
                int count = 0;
                while (true) {
                    left--;
                    count++;
                    if (left < 0) {
                        left = nums.length - 1;
                    }
                    if (nums[left] == query) {
                        res[i] = count;
                        break;
                    }
                    right++;
                    if (right > nums.length - 1) {
                        right = 0;
                    }
                    if (nums[right] == query) {
                        res[i] = count;
                        break;
                    }
                }
                continue;
            }
            // 使用记录的数组进行遍历
            for (int j = 0; j < list.size(); j++) {
                int val = list.get(j);
                if (val == index) {
                    // 当前查询的位置,比较左边和右边的距离取较小值
                    int left = j == 0 ? val + nums.length - list.get(list.size() - 1) : val - list.get(j - 1);
                    int right = j == list.size() - 1 ? nums.length - val + list.get(0) : list.get(j + 1) - val;
                    res[i] = Math.min(left, right);
                    break;
                }
            }
        }
        return IntStream.of(res).boxed().collect(Collectors.toList());
    }
}
相关推荐
先吃饱再说12 小时前
判断回文字符串,从一行代码到双指针优化
算法
黄敬峰15 小时前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术16 小时前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六19 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术20 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize21 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
罗西的思考1 天前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队2 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode