[Question]
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.
[Analysis]
If using brute force, going through each nums[i] and checking whether any of nums[i+1],..., nums[i+k] values are within the range of [ nums[i]-t, nums[i]+t ], the time complexity is O( K^2 * N ).
Making a BST for the sub-array { nums[i+1],..., nums[i+k] }, and find if any values in the BST fall into [ nums[i]-t, nums[i]+t ], the time complexity is O(log K * N).
The interesting part of the C++ code below is, how to use "multiset" as a BST and fulfill the above logic in just a few lines.
Update: Using bucket sort is a better solution. The time complexity is O(N).
[Solution]
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if (nums.empty() || k<=0 || t<0) return false;
multiset<int> bst (nums.begin(), nums.begin()+k);
for (int i=0; i<nums.size(); i++) {
bst.erase(bst.find(nums[i]) );
if (i+k<nums.size()) bst.insert(nums[i+k]);
// -- make sure the boundary condition --
if (bst.find(nums[i]+t)!=bst.end() || bst.find(nums[i]-t)!=bst.end() ) return true;
if (bst.upper_bound(nums[i]+t) != bst.upper_bound(nums[i]-t)) return true;
}
return false;
}
};
//-- Bucket Sort --
class Solution {
public:
bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
if (k<1 || t<0) return false;
int min_elem = *min_element(nums.begin(), nums.end());
unordered_map<long, long> buckets;
for(int i=0; i<nums.size(); i++) {
long key = (nums[i]-min_elem) / (t+1);
if (buckets.count(key)>0) return true;
if (buckets.count(key-1)>0 && abs(nums[i]-buckets[key-1]) <= t
|| buckets.count(key+1)>0 && abs(nums[i]-buckets[key+1]) <=t)
return true;
buckets[key] = (long)nums[i];
if (i>=k) buckets.erase( (nums[i-k]-min_elem)/(t+1) );
}
return false;
}
};
No comments:
Post a Comment