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

[leetcode ]220.Contains Duplicate III

2015-07-25 16:19 465 查看
题目:

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.

题意:

在数组中找出是否存在两个不同的数,数字之间的距离小于等于k,两个数字最大相差t。

思路:

这是第二道题继续延伸过来。第二道题请参考我的上一篇博客/article/9676047.html

这道题变化的是不是判断两个数相等,而是两个数相差的范围小于等于某个给定值。我们上一题的思路是使用hash来记录窗口大小是k的数据。依旧使用hash的方法来完成。我们其实可以将题目转变为与上一题一样的解法。比如我们现在有两个数字m,n,如果m与n满足两者相差小于等于k,那么我们可以得到的是m / k == n / k 如果m是k的倍数,并且n也是k的倍数,那么可能|m/k- n/k| ==1,综合起来就是|m/k- n/k| <=1.也就是说我们将每个数字除上k,那么就相当于压缩了数据到第二题的情形。

所以这次对于每个数字nums[i]进行先除去k的操作,得到m,如果之前窗口中有满足条件的结果值,那么有三种可能:

key值m在窗口中已经记录了值,这就代表着nums[j] / k也等于m,所以nums[j]与nums[i]满足条件。

key值m-1在窗口中记录了值,并且abs(map[m-1] - nums[i]) <= t;

key值m+1在窗口中记录了值,并且abs(map[m+1] - nums[i]) <= t;

需要考虑负数情况,比如-3,3如果t=4,那么-3/4==0,3/4==0,然-3,3并不满足条件,本文中将数字全部加上int的最大值转变为long long类型,确保全部非负。

以上。

代码如下:

class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if(nums.size() == 0 || k <= 0 || t < 0)return false;
unordered_map<long long,int> window;
for(int i = 0; i < nums.size(); i++) {
long long bucket = ((long long)nums[i] + INT_MAX)/(t + 1);
if(window.find(bucket) != window.end() || (window.find(bucket - 1) != window.end() && abs((long long)nums[i] - window[bucket - 1]) <= t) || (window.find(bucket + 1) != window.end() && abs((long long)nums[i] - window[bucket + 1]) <= t))
return true;
if(window.size() == k) {
long long last_bucket = ((long long)nums[i - k] + INT_MAX)/(t + 1);
window.erase(last_bucket);
}
window[bucket] = nums[i];
}
return false;
}
};


还可以使用二叉搜索树(红黑树)来进行查找操作。做法是使用set来保存前k个元素,到达第k+1个元素的时候,查看大于等于nums[k+1] - t的第一个元素,使用STL的lower_bound进行查找。然后判断这个元素是否满足与nums[k+1]的差距在t的范围之内,即abs(nums[k+1] - *iter)是否小于等于t。因为我们使用lower_bound查找的时候,找到的元素比nums[k+1] - t大,但是也有可能太大,所以要查看这个元素与nums[k+1]的距离是否是在t的范围之内。

以上。

代码如下:

class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if(nums.size() == 0 || k <= 0 || t < 0)return false;
set<int> window;
int size = nums.size();
for(int i = 0; i < size; i++) {
if(i > k) {
window.erase(nums[i - k - 1]);
}
auto iter = window.lower_bound(nums[i] - t);
if(iter != window.end() && abs(nums[i] - *iter) <= t)
return true;
window.insert(nums[i]);
}
return false;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: