前k个数中有某数与当前数相差<=t
滑动窗口内的数放入set,O(nlgk):
bool containsNearbyAlmostDuplicate(vector<int> &nums, int k, int t) {
if (t < 0) return false;
set<long> st; // 把前k个数放入set中
for (int i = 0; i < nums.size(); i++) {
// 在st中找x,abs(nums[i]-x)<=t,nums[i]-t<=x<=nums[i]+t
// 只要找>=nums[i]-t的最小数,看它是否<=nums[i]+t
auto it = st.lower_bound((long)nums[i] - t);
if (it != st.end() && *it <= (long)nums[i] + t) return true;
st.insert(nums[i]);
if (st.size() > k) st.erase(nums[i-k]);
}
return false;
}
桶排序法,O(n):
bool containsNearbyAlmostDuplicate(vector<int> &nums, int k, int t) {
if (t < 0) return false;
unordered_map<long, long> buckets; // bucketIdxOfNum=>num
// buckets保存前k个数,buckets.size()<=k
for (int i = 0; i < nums.size(); i++) {
auto idx = bucketIdx(nums[i], t);
// 又落在自己桶
if (buckets.count(idx)) return true;
// 检查相邻两桶
if (buckets.count(idx-1) && nums[i] - buckets[idx-1] <= t) return true;
if (buckets.count(idx+1) && buckets[idx+1] - nums[i] <= t) return true;
buckets[idx] = nums[i];
if (buckets.size() > k) buckets.erase(bucketIdx(nums[i-k], t));
}
return false;
}
// |x-y|<=t有[0..t]个值,桶长t+1时落在一个桶中的值肯定重复
long bucketIdx(long num, long t) {
return (num - INT_MIN) / (t + 1);
}