每日一道leetcode(2026.04.10):三个相等元素之间的最小距离 I

每日一道leetcode(2026.04.10):三个相等元素之间的最小距离 I

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

1. 题目

给你一个整数数组 nums。

如果满足 nums[i] == nums[j] == nums[k],且 (i, j, k) 是 3 个 不同 下标,那么三元组 (i, j, k) 被称为 有效三元组 。有效三元组 的 距离 被定义为 abs(i - j) + abs(j - k) + abs(k - i),其中 abs(x) 表示 x 的绝对值 。返回一个整数,表示 有效三元组 的 最小 可能距离。如果不存在 有效三元组 ,返回 -1。

示例 1:

输入: nums = [1,2,1,1,3]

输出: 6

解释:

最小距离对应的有效三元组是 (0, 2, 3) 。

(0, 2, 3) 是一个有效三元组,因为 nums[0] == nums[2] == nums[3] == 1。它的距离为 abs(0 - 2) + abs(2 - 3) + abs(3 - 0) = 2 + 1 + 3 = 6。

示例 2:

输入: nums = [1,1,2,3,2,1,2]

输出: 8

解释:

最小距离对应的有效三元组是 (2, 4, 6) 。

(2, 4, 6) 是一个有效三元组,因为 nums[2] == nums[4] == nums[6] == 2。它的距离为 abs(2 - 4) + abs(4 - 6) + abs(6 - 2) = 2 + 2 + 4 = 8。

示例 3:

输入: nums = [1]

输出: -1

解释:

不存在有效三元组,因此答案为 -1。

提示:

1 <= n == nums.length <= 100

1 <= nums[i] <= n

2. 分析

这道题比较简单,按照我的思路,把所有的元素,按照数值放到一个map里面,键为数值,值为相同数值的所有下标组成的数组,然后过滤出数组长度大于等于3的情况,再求出所有距离最小的。这里稍稍麻烦一些的是当数组长度大于3时,需要遍历所有情况的组合。

3. 代码实现

java 复制代码
class Solution {
    public int minimumDistance(int[] nums) {
        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<>());
            }
            map.get(nums[i]).add(i);
        }
        return map.values().stream().filter(integers -> integers.size() >= 3)
                .map(this::dfs).mapToInt(v -> v).min()
                .orElse(-1);
    }

    private int dfs(List<Integer> list) {
        if (list.size() == 3) {
            return distance(list, 0, 1, 2);
        }
        return minDistance(list, 0, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE);
    }

    private int minDistance(List<Integer> list, int index,
            int first, int second, int third, int minDistance) {
        if (index >= list.size()) {
            return minDistance;
        }
        // 选择
        if (first == Integer.MIN_VALUE) {
            minDistance = minDistance(list, index + 1, index, second, third, minDistance);
        } else if (second == Integer.MIN_VALUE) {
            minDistance = minDistance(list, index + 1, first, index, third, minDistance);
        } else if (third == Integer.MIN_VALUE) {
            minDistance = Math.min(minDistance, distance(list, first, second, index));
        }
        // 不选择
        if (index == list.size() - 1) {
            return minDistance;
        }
        return Math.min(minDistance, minDistance(list, index + 1, first, second, third, minDistance));
    }

    private int distance(List<Integer> list, int i, int j, int k) {
        return Math.abs(list.get(i) - list.get(j)) +
                Math.abs(list.get(i) - list.get(k)) +
                Math.abs(list.get(j) - list.get(k));
    }
}

4. 总结

执行结果只击败了6%,意料之中,在写数组遍历时就意料到此方法的劣势,如果有多个长度大于3的数组,会增加很多层遍历,性能损耗较大。

下面是官方的题解,确实更优,使用三层循环,分别对应原数组上不同下标的三个元素,第一个的范围是0到n-3,第二个的范围是1到n-2,第三个的范围是2到n-1,然后当三者的值相等时,计算一次距离,以此遍历,可以快速计算出最小的距离,少了很多循环。

java 复制代码
class Solution {
    public int minimumDistance(int[] nums) {
        int n = nums.length;
        int ans = n + 1;

        for (int i = 0; i < n - 2; i++) {
            for (int j = i + 1; j < n - 1; j++) {
                if (nums[i] != nums[j]) {
                    continue;
                }
                for (int k = j + 1; k < n; k++) {
                    if (nums[j] == nums[k]) {
                        ans = Math.min(ans, k - i);
                        break;
                    }
                }
            }
        }

        return ans == n + 1 ? -1 : ans * 2;
    }
}
相关推荐
nlpming2 小时前
OpenClaw 代码解析
算法
学习永无止境@2 小时前
MATLAB中矩阵转置
算法·matlab·fpga开发·矩阵
七颗糖很甜2 小时前
雨滴谱数据深度解析——从原始变量到科学产品的Python实现【下篇】
python·算法·pandas
nlpming2 小时前
OpenClaw system prompt定义
算法
nlpming2 小时前
OpenClaw安装配置及简介
算法
爱码小白2 小时前
MySQL 常用数据类型的系统总结
数据库·python·算法
玛丽莲茼蒿2 小时前
Leetcode hot100 【中等】括号生成
算法·leetcode·职场和发展
小欣加油2 小时前
leetcode 128 最长连续序列
c++·算法·leetcode·职场和发展
汀、人工智能2 小时前
[特殊字符] 第94课:删除无效的括号
数据结构·算法·数据库架构·图论·bfs·删除无效的括号