1.题目:
给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。
如果存在则返回 true,不存在返回 false。
示例 1:
输入:nums = [1,2,3,1], k = 3, t = 0
输出:true
原题链接:220.存在重复元素 III
2.思路:①题目中给出了两个数组下标的范围 abs(i - j) <= k,如何将元素限制在这个范围中?
从这一点我们可以想到需要使用滑动窗口的方法,通过滑动窗口将两个数组限制在k范围中。
②如何对该范围中的元素进行排序,使其满足abs(nums[i] - nums[j]) <= t?
这里我们可以采取有序的数据结构。
- 在C++中set/multiset/map内部元素是有序的,它们都是基于红黑树实现的。其中set会对元素进行去重,multiset可以有重复元素,map是有序的哈希表。
- 在Java中TreeSet/TreeeMap内部元素是有序的,它们也是基于红黑树实现的,TreeSet是有序的去重集合,TreeMap是key有序的哈希表。
3.代码:
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
set<long int> st;
int left = 0;
for (int right = 0;right < nums.size();right++)
{
//超出滑动窗口的长度
if (right - left > k)
{
st.erase(nums[left]);
left++;
}
//找是否存在小于nums[right]-t的元素
//lower_bound函数二分查找一个有序数列,返回第一个大于等于x的数,如果没找到,返回末尾的迭代器位置
auto a = st.lower_bound((long long)nums[right]-t);
if (a != st.end() && abs(*a - nums[right]) <= t)
{
return true;
}
st.insert(nums[right]);
}
return false;
}
};