题目
- 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。
示例
①示例1
- 输入: nums = [1,2,3,1], k = 3, t = 0
- 输出: true
②示例2
- 输入: nums = [1,0,1,1], k = 1, t = 2
- 输出: true
③示例3
- 输入: nums = [1,5,9,1,5,9], k = 2, t = 3
- 输出: false
说明
①数据范围(自测)
②相关话题
③相似题目
④题目地址
解题方法
①滑动窗口 + 哈希表
- 这道题的数据范围很大,每组数据值的波动幅度也很大,所以不能用数组模拟的哈希表求解,需要使用 uthash。
- uthash 是一个用 C 语言编写的开源库,使用宏实现了哈希表的增删改查等功能。
- 我们需要使用滑动窗口和查找表,不断地查找当前哈希表中是否存在
∣
n
u
m
s
[
i
]
−
键
值
∣
<
=
t
|nums[i]-键值| <= t
∣nums[i]−键值∣<=t。并且当滑动窗口的大小大于 k 时,需要移除哈希表中最左边的元素,保证窗口中最多有 k 个元素。
- 时间复杂度:O(N^2)。
- 空间复杂度:O(N)。
②暴力解法
- 两层 for 循环暴力判断。
- 时间复杂度:O(N^2)。
- 空间复杂度:O(1)。
代码详解
bool containsNearbyAlmostDuplicate(int* nums, int numsSize, int k, int t) {
struct hash {
int value;
UT_hash_handle hh;
};
struct hash *hashTable = NULL;
int len = 0;
for (int i = 0; i < numsSize; i++) {
struct hash *h1, *h2;
if (len > k) {
HASH_FIND_INT(hashTable, nums+len-k-1, h1);
HASH_DEL(hashTable, h1);
}
for (struct hash *s = hashTable; s!= NULL; s = s->hh.next) {
if (labs((long)nums[i]-(long)s->value) <= t)
return true;
}
HASH_FIND_INT(hashTable, nums+i, h2);
if (!h2) {
h2 = malloc(sizeof(struct hash));
h2->value = nums[i];
HASH_ADD_INT(hashTable, value, h2);
len++;
}
}
return false;
}
bool containsNearbyAlmostDuplicate(int* nums, int numsSize, int k, int t) {
for (int i = 0; i < numsSize; i++) {
int limit = i+k >= numsSize? numsSize: i+k+1;
for (int j = i+1; j < limit; j++) {
if (labs((long)nums[i]-(long)nums[j]) <= t)
return true;
}
}
return false;
}
附录