存在重复元素 II
题目
给定一个整数数组和一个整数 k
,判断数组中是否存在两个不同的索引 i
和 j
,使得
n
u
m
s
[
i
]
=
n
u
m
s
[
j
]
nums [i] = nums [j]
nums[i]=nums[j],并且 i
和 j
的差的 绝对值 至多为 k
。
示例 1:
输入: nums = [1,2,3,1], k = 3
输出: true
示例 2:
输入: nums = [1,0,1,1], k = 1
输出: true
示例 3:
输入: nums = [1,2,3,1,2,3], k = 2
输出: false
函数原型
C
的函数原型:
bool containsNearbyDuplicate(int* nums, int numsSize, int k){}
边界判断
bool containsNearbyDuplicate(int* nums, int numsSize, int k){
if( nums == NULL || numsSize == NULL )
return false;
}
算法设计:滑动窗口 + 查找表
n
u
m
s
[
i
]
=
n
u
m
s
[
j
]
nums [i] = nums [j]
nums[i]=nums[j],并且 i
和 j
的差的 绝对值 至多为 k
。
也就是说
n
u
m
s
[
i
]
、
n
u
m
s
[
j
]
nums [i] 、nums [j]
nums[i]、nums[j] 存储的是同一个元素。
因为
j
−
i
<
=
k
j-i <= k
j−i<=k,那它们一定在某个区间
[
l
,
l
+
k
]
[l,~ l+k]
[l, l+k] 里:
这个区间有
k
+
1
k+1
k+1 个元素,如果在
k
+
1
k+1
k+1 个元素中,能找到俩个相同的元素,不就满足
j
−
i
<
=
k
j-i <= k
j−i<=k 啦。
所以,问题就是:在这个数组中,能不能找到某个区间,这个区间存在俩个相同的元素。
思路:找一个范围使得其值满足某个条件,然后就会想到滑动窗口。
假设查找的是这样一个区间:
当前区间并没有相同元素,所以要去看下一个元素(向右扩展)
看下一个元素的同时,为了维持窗口范围,左边也得收缩一下:
而后考虑的是,新元素(红色)在区间
[
l
+
1
,
l
+
k
]
[l+1,~l+k]
[l+1, l+k] 中有木有相同的元素。
俩种情况:
- 有相同元素,即找到了,的确存在这样的区间
- 没有相同元素,就继续找,直到找遍整个数组,说明没有这样的区间
#include<uthash.h> /* C语言哈希库 */
typedef struct hash{
int key; // 键
int index; // 索引值
UT_hash_handle hh; // 让结构体哈希柄
} *hash_ptr;
bool containsNearbyDuplicate(int* nums, int numsSize, int k){
hash_ptr p = NULL, tables = NULL;
for(int i=0; i<numsSize; i++){
if( tables )
HASH_FIND_INT(tables, &(nums[i]), p);
if( p && (i-p->index) <= k )
return true;
p=(hash_ptr)malloc(sizeof(*p));
p->key=nums[i];
p->index=i;
HASH_ADD_INT(tables, key, p);
}
free(p), p = NULL;
return false;
}
- 时间复杂度: Θ ( n ) \Theta(n) Θ(n)
- 空间复杂度: Θ ( m i n ( n , k ) ) \Theta(min(n, k)) Θ(min(n,k))