Lesson learnt: std::multiset<T> is a heap structure supporting random removal...
class Solution { public: bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) { if (t < 0) return false; size_t len = nums.size(); k = std::min(k, (int)len - 1); if (k <= 0) return false; std::multiset<long long> hp; for (int i = 0; i < len; i ++) { if (i > k) { hp.erase(nums[i - k - 1]); // heap maintain } int curr = nums[i]; if (hp.find(curr) != hp.end()) return true; // Upper bound auto up = hp.upper_bound(curr); if(up != hp.end() && *up - curr <= t) return true; // Lower bound if (up != hp.begin()) { --up; if ((curr - *up) <= t) return true; } hp.insert(curr); } return false; } };
Or, another incredibly smart solution: bucketing! https://leetcode.com/discuss/38206/ac-o-n-solution-in-java-using-buckets-with-explanation
class Solution { public: bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) { if (k < 1 || t < 0) return false; unordered_map<long long, long long> hm; for (int i = 0; i < nums.size(); i ++) { long long nv = (long long)nums[i] - INT_MIN; long long bucket = nv / ((long long)t + 1); if ( hm.find(bucket) != hm.end() || (hm.find(bucket + 1) != hm.end() && (hm[bucket + 1] - nv) <= t) || (hm.find(bucket - 1) != hm.end() && (nv - hm[bucket - 1]) <= t) ) return true; // if (hm.size() >= k) { long long lastBucket = ((long long)nums[i - k] - INT_MIN) / ((long long)t + 1); hm.erase(lastBucket); } hm[bucket] = nv; } return false; } };