Easy
题目描述
给你一个整数数组 nums (下标从 0 开始)和两个整数 target 和 start,请你找出一个下标 i,使得 nums[i] == target 且 abs(i - start) 的值最小。注意 abs(x) 表示 x 的绝对值。
返回 abs(i - start)。
题目数据保证 target 存在于 nums 中。
示例 1:
输入:nums = [1,2,3,4,5], target = 5, start = 3
输出:1
解释:nums[4] = 5 是唯一一个等于 target 的值,所以答案是 abs(4 - 3) = 1 。
示例 2:
输入:nums = [1], target = 1, start = 0
输出:0
解释:nums[0] = 1 是唯一一个等于 target 的值,所以答案是 abs(0 - 0) = 0 。
示例 3:
输入:nums = [1,1,1,1,1,1,1,1,1,1], target = 1, start = 0
输出:0
解释:nums 中每个值都是 1 ,但 nums[0] 使 abs(i - start) 的值最小,为 abs(0 - 0) = 0 。
提示:
1 <= nums.length <= 10001 <= nums[i] <= 10^40 <= start < nums.lengthtarget存在于nums中
解题思路
这道题要求找到数组中等于目标值且距离起始位置最近的元素索引。
解法分析
方法一:暴力遍历 最直接的方法是遍历整个数组,找到所有等于 target 的元素,计算它们与 start 的距离,返回最小距离。
方法二:双向扩展(推荐) 从 start 位置开始,向左右两个方向同时扩展搜索。这样一旦找到目标元素,就能保证是距离最近的,可以立即返回结果,避免不必要的遍历。
具体实现:
- 首先检查 start 位置是否就是目标值
- 然后同时向左右扩展,distance 从 1 开始递增
- 检查 start-distance 和 start+distance 位置的值
- 一旦找到目标值立即返回当前距离
双向扩展的优势在于:
- 时间复杂度在最好情况下可以达到 O(1)
- 平均情况下比暴力遍历更快
- 代码逻辑清晰,易于理解
方法三:分别向左右查找 也可以分别向左和向右查找最近的目标元素,然后比较两个距离取最小值。
代码实现
class Solution {
public:
int getMinDistance(vector<int>& nums, int target, int start) {
int n = nums.size();
// 从start位置开始双向扩展
for (int distance = 0; distance < n; distance++) {
// 检查左边
if (start - distance >= 0 && nums[start - distance] == target) {
return distance;
}
// 检查右边
if (start + distance < n && nums[start + distance] == target) {
return distance;
}
}
return -1; // 不会执行到这里,因为题目保证target存在
}
};
class Solution:
def getMinDistance(self, nums: List[int], target: int, start: int) -> int:
n = len(nums)
# 从start位置开始双向扩展
for distance in range(n):
# 检查左边
if start - distance >= 0 and nums[start - distance] == target:
return distance
# 检查右边
if start + distance < n and nums[start + distance] == target:
return distance
return -1 # 不会执行到这里,因为题目保证target存在
public class Solution {
public int GetMinDistance(int[] nums, int target, int start) {
int n = nums.Length;
// 从start位置开始双向扩展
for (int distance = 0; distance < n; distance++) {
// 检查左边
if (start - distance >= 0 && nums[start - distance] == target) {
return distance;
}
// 检查右边
if (start + distance < n && nums[start + distance] == target) {
return distance;
}
}
return -1; // 不会执行到这里,因为题目保证target存在
}
}
var getMinDistance = function(nums, target, start) {
const n = nums.length;
// 从start位置开始双向扩展
for (let distance = 0; distance < n; distance++) {
// 检查左边
if (start - distance >= 0 && nums[start - distance]
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(n),最坏情况下需要遍历整个数组,但平均情况下会更快 |
| 空间复杂度 | O(1),只使用常数级额外空间 |