文章目录

题目描述

示例 1:
输入: nums = [12,21,45,33,54]
输出: 1
解释:
镜像对为:
(0, 1),因为 reverse(nums[0]) = reverse(12) = 21 = nums[1],绝对距离为 abs(0 - 1) = 1。
(2, 4),因为 reverse(nums[2]) = reverse(45) = 54 = nums[4],绝对距离为 abs(2 - 4) = 2。
所有镜像对中的最小绝对距离是 1。
示例 2:输入: nums = [120,21]
输出: 1
解释:
只有一个镜像对 (0, 1),因为 reverse(nums[0]) = reverse(120) = 21 = nums[1]。
最小绝对距离是 1。
示例 3:输入: nums = [21,120]
输出: -1
解释:
数组中不存在镜像对。
提示:1 <= nums.length <= 105
1 <= nums[i] <= 109
思路简述
在初次尝试解决这道题时,我的第一反应是利用哈希表记录数组中元素的下标,遍历数组时在哈希表中查找对应的镜像数,进而计算距离。但很快发现,这种方法在处理数组中存在重复元素的情况时,无法保证计算出的距离是最小的,因此需要转换思路。
我们可以设计这样一个哈希表:键(Key)是某个数镜像反转后的值,值(Value)是该镜像数在原数组中对应的下标 。换句话说,如果 hash[v] = j,就意味着在下标 j 的位置,存在一个数 nums[j],其反转后的值恰好等于 v。
由于我们是从左到右遍历数组的,哈希表中存储的下标一定是距离当前位置最近的(因为哈希表的键是唯一的,后续更近的下标会覆盖之前较远的下标)。
基于这个设计,遍历过程中会出现两种情况:
-
当我们遍历到当前数
nums[i]时,如果它存在于哈希表中,说明在之前的位置中,有一个数的镜像值正好等于当前数,且那个数的下标就是hash[nums[i]]。此时,我们直接计算这两个下标之间的绝对距离abs(hash[nums[i]] - i),并尝试更新最小距离。 -
无论当前数是否在哈希表中,我们都需要将当前数的镜像值及其下标
i存入哈希表。这一步正是保证我们能获取最小距离的关键:如果哈希表中之前没有这个镜像值,那么这次存入是第一次记录;如果之前已经有了,那么用当前更近的下标i覆盖之前的下标,这样后续遇到匹配的数时,计算出的距离一定是更小的。
这个思路虽然在设计和对哈希表的理解上稍稍绕一点,但是巧妙地解决了最棘手的重复元素问题和最小距离的保证问题。
至于如何实现求整数镜像值的函数,有很多种实现方式,我用的是通过模运算(%)取最后一位,再通过除法(/)去掉最后一位,逐步构建出反转后的数。
代码实现
cpp
class Solution {
public:
// 函数功能:将整数 x 的数字反转,忽略前导零
// 例如:rev(120) -> 21,rev(12) -> 21
int rev(int x)
{
int y = 0; // 用于存储反转后的结果
while (x > 0)
{
y = y * 10 + x % 10; // 取出 x 的最后一位,加到 y 的末尾
x /= 10; // 去掉 x 的最后一位
}
return y;
}
int minMirrorPairDistance(vector<int>& nums)
{
unordered_map<int,int> hash; // 哈希表:键是镜像后的值,值是原数的下标
int ret = INT_MAX; // 初始化最小距离为最大整数,表示尚未找到任何镜像对
for(int i = 0; i < nums.size(); i++)
{
int x = nums[i];
// 情况1:如果当前数 x 存在于哈希表中,说明前面有它的镜像数
if(hash.count(x))
{
// 计算当前下标与哈希表中存储的下标的距离,并更新最小距离
ret = min(ret, abs(hash[x] - i));
}
// 情况2:无论是否找到镜像对,都将当前数的镜像值和下标存入哈希表
// 这样可以保证后续遇到匹配的数时,拿到的是最近的下标
hash[rev(x)] = i;
}
// 如果 ret 仍然是初始值,说明没有找到镜像对,返回 -1;否则返回最小距离
return ret == INT_MAX ? -1 : ret;
}
};
复杂度分析
时间复杂度 : O ( n ) O(n) O(n),其中 n n n 为数组长度。
我们仅需对数组进行一次遍历,遍历过程中哈希表的查询、插入操作均为 O ( 1 ) O(1) O(1) 平均时间复杂度;数字反转函数的执行次数与数字位数成正比,属于常数级操作,因此整体时间复杂度为线性,完全适配 10 5 10^5 105 的数据规模。
空间复杂度 : O ( n ) O(n) O(n)。
最坏情况下数组中所有元素的反转值均不重复,哈希表需要存储 n n n 个键值对,因此空间复杂度为 O ( n ) O(n) O(n)。
踩坑记录
- 一定要明确哈希表的键值含义:一定要弄明白哈希表中键和值各自代表的是什么------键是"镜像后的值",值是"原数的下标"。如果在这一点上混淆了,很容易在后续的查找和更新操作中出错,导致逻辑混乱。
- 注意最小距离变量的初始化 :在初始化用于记录最小距离的变量
ret时,要将其设置为一个足够大的值(例如INT_MAX),这样在第一次找到有效距离时,才能正确地将其更新为第一个候选值。如果初始值过小,可能会导致后续无法正确更新。
如果这篇内容帮你理清了哈希表的设计逻辑,避开了我踩过的坑,麻烦大家动动小手点个赞,也可以把文章收藏起来,不管是后续刷题复盘、还是面试前回顾,都能随时翻出来看。
想要跟着刷更多 LeetCode 每日一题、解锁更多算法解题技巧的小伙伴,一定要关注我呀!后续会持续更新超详细的题解、算法思路和避坑指南,陪你一起刷穿题库,稳稳拿下算法关~
