一. 题目描述
Given an array of integers, find out whether there are two distinct indices i
and j
in the array such that the difference between nums[i]
and nums[j]
is at most t and the difference between i
and j
is at most k
.
二. 题目分析
题目大意是,给定一个整数数组,判断其中是否存在两个不同的下标i
和j
,满足:| nums[i] - nums[j] | <= t
且下标:| i - j | <= k
。
可以想到,维护一个大小为k
的二叉搜索树BST
,遍历数组中的元素,在BST
上搜索有没有符合条件的数对,若存在则直接返回true,否则将当前元素数对插入BST
,并更新这个BST
(若此时BST
的大小已为k,需要删掉一个值)。保证BST
的大小小于或等于为k
,是为了保证里面的数下标差值一定符合条件:| i - j | <= k
。实现时,可使用mulitset
来实现BST
。
mulitset是一个有序的容器,里面的元素都是排序好的,且允许出现重复的元素,支持插入,删除,查找等操作,就像一个集合一样。multiset内部以平衡二叉树实现。因此所有的操作的都是严格在O(logn)
时间之内完成,效率较高。
三. 示例代码
// 方法一,由于vector无序,需要排列一次
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if(nums.size() < 2) return false;
vector<pair<long, int>> value;
for (int i = 0; i < nums.size(); ++i)
value.push_back(pair<long, int>(nums[i], i));
sort(value.begin(), value.end());
for (int i = nums.size() - 1; i >= 1; --i)
{
for (int j = i - 1; j >= 0; --j)
{
if (value[i].first - value[j].first > t) break;
else if (abs(value[i].second - value[j].second) <= k) return true;
else continue;
}
}
return false;
}
};
// 方法二
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
multiset<int> window; // 维护一个大小为k的窗口
for (int i = 0; i < nums.size(); ++i) {
if (i > k) window.erase(nums[i - k - 1]); // 保持window内只有最新k个元素,间接保证窗口内各元素下标不超过k
auto pos = window.lower_bound(nums[i] - t);
if (pos != window.end() && *pos - nums[i] <= t) return true;
window.insert(nums[i]);
}
return false;
}
四. 小结
练习了集合类set和mulitset的使用。相关题目有:Contains Duplicate II和Contains Duplicate I
时间: 2024-10-13 13:57:25