LeetCode/solutions/220. Contains Duplicate III.md
2019-09-11 19:53:15 +08:00

57 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [220. Contains Duplicate III](https://leetcode.com/problems/contains-duplicate-iii/)
# 思路
给定一个数组. 判断是否满足: 存在两个元素两个元素的下标差的绝对值不能大于k值差的绝对值不能大于t。
基本思路很好想: 用一个大小为k起始下标为i+1的滑窗,
判断滑窗内是否存某个元素使nums[i]与此元素之差的绝对值不大于t(即找到滑窗内与nums[i]最接近的那个元素判断二者之差的绝对值是否不大于t).
如果我们暴力地遍历一遍滑窗内元素来判断"是否存某个元素使nums[i]与此元素之差的绝对值不大于t"的话每次判断复杂度为O(k),
但是如果我们始终将滑窗内的元素维护成有序的话查找复杂度就为log(k)了, 而平衡二叉树(或其改进版)红黑树)的插入,删除,查找的复杂度都是logN级别, 满足我们需要.
而在STL中, 内部实现为红黑树的容器有set和map(其实还有multimap和multiset).
另外为了找到与nums[i]最接近的x使`|nums[i]-x| <= t`, 即`nums[i]-x <= t`且`nums[i]-x >= -t`, 即`nums[i]-t <= x`且`x-nums[i] <= t`,
我们可以先用二分法lower_bound找到满足`nums[i]-t <= x`的x, 再判断是否满足`x-nums[i] <= t`即可.
* 注意map和set在插入时写法不同, 另外根据迭代器访问值的写法也不一样.
* 灵活运用lower_bound和upper_bound.
# C++
## 用map
``` C++
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
map<long long, int> window; // 用long long是为了防止溢出
for(int i = 0; i < nums.size(); i++){
if(i > k) window.erase(nums[i - k - 1]); // 保持k个值
auto x = window.lower_bound((long long)nums[i] - t);
if(x != window.end() && (x -> first - nums[i]) <= t)
return true;
window[nums[i]] = i; // 等于任意值都可以
}
return false;
}
};
```
## 用set
``` C++
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
set<long long> window;
for(int i = 0; i < nums.size(); i++){
if(i > k) window.erase(nums[i - k - 1]); // 去除掉窗口范围外的值
auto x = window.lower_bound((long long)nums[i] - t);
if(x != window.end() && (*x - nums[i]) <= t) // 注意写法
return true;
window.insert(nums[i]); // 注意写法
}
return false;
}
};
```