您的位置:首页 > 大数据 > 人工智能

Leetcode 220. Contains Duplicate III

2018-04-09 23:20 357 查看
Given an array of integers, find out whether there are two distinct indices i and j in the array such that the absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.

s思路:

1. 看了提示,用binary search tree。用BST,在c++就是用set或map了,因为这两样就是用bst实现的。

2. 因为没有重复,所以不能用hash。坐标之差在一个范围内,我们可以每次只在这个范围内寻找数,比如:从左往右移动,当长度大于k,那么就把搜索区间的最左边删除,类似与two pointer的方法,只是这个窗口达到k后就不增加了;

3. 数据之差如何搞定呢?当然可以在窗口内双重循环找到所有数据之差然后判断是否存在一个数据差小于t,但这样复杂度就是o(k^2),由于没窗口每次移动一下,都要这样来一遍,所以总的复杂度o(nk^2),还是太大。

4. 主要的问题是:在k长的窗口内,是否存在|nums[i]-nums[j]|<=t的一对数据?由于数据是无序的,难道一定要遍历所有o(k^2)的可能吗?这几天都在说,要从无序中看出是否有序的可能,先不说马上能看到,但一定要有信念,不然真看不到,因为心里着急,气急败坏,没有信心嘛。

5. 先把上面的不等式展开:-t<=nums[i]-nums[j]<=t,继续处理:

nums[i]-t<=nums[j]<=nums[i]+t


注意看,这就和原来不一样了,我们假设i是从左往右遍历的当前的数的index,而j

//方法1:用set,
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
//
set<long> ss;//bug:调试很久,刚开始用int,发现要做运算,极限case过不了,所以用long保护
for(int i=0;i<nums.size();i++){
if(i>k) ss.erase(nums[i-k-1]);
set<long>::iterator it=ss.lower_bound((long)nums[i]-t); //bug:只需要把其中之一转换成long即可
if(it!=ss.end() && (*it)-nums[i]<=t) return true;
ss.insert(nums[i]);
}
return false;
}
};

//优化1:不用每次都把nums[i]转成long,考虑到两个数相加减,如果一个数是long,另一个是int,那么结果仍是long.所以不如把t转换成long,果然快一些!
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
//
set<long> ss;
long lt=t;
for(int i=0;i<nums.size();i++){
if(i>k) ss.erase(nums[i-k-1]);
set<long>::iterator it=ss.lower_bound(nums[i]-lt);
if(it!=ss.end() && (*it)-nums[i]<=lt) return true;
ss.insert(nums[i]);
}
return false;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bst 范围搜索 set