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就可以满足要求,返回true。 这里使用multiset来实现,因为其底层使用的是红黑数,一斤排好序了,而且查找性能好,不会出现out of time的情况,主要的想法是遍历vector,当multiset的大小小于k的时候插入,判断当前值在整个set中是否有值与其相差t及以下,由于存在lower_bound,还是比较方便的。
1 class Solution { 2 public: 3 bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) { 4 multiset<long long> ret; 5 int sz = nums.size(); 6 for (int i = 0; i < sz; ++i){ 7 if (ret.size() == k + 1) 8 ret.erase(ret.find(nums[i - k -1])); 9 auto lb = ret.lower_bound(nums[i] - t); // 这个表达式规定了*lb - nums[i] > -t 10 if (lb != ret.end() && *lb - nums[i] <= t)return true; //这个规定了*lb - num[i] < t; 11 ret.insert(nums[i]); 12 } 13 return false; 14 } 15 };
感觉以前写的c++的版本写的比较怪,下面是java写的,其实维持一个长度为k的窗口不一定需要用multiSet直接使用java中的treeSet接可以维持一个,lower_bound以及upper_bound函数实际上也是不需要的,代码如下所示:
1 public class Solution { 2 public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { 3 if(k < 1|| t < 0 || nums == null || nums.length < 2) 4 return false; 5 SortedSet<Long> set = new TreeSet<Long>(); 6 for(int i = 0; i < nums.length; ++i){ 7 SortedSet<Long> subSet = set.subSet((long)nums[i] - t, (long)nums[i] + t + 1); 8 if(!subSet.isEmpty()) 9 return true; 10 if(i >= k){//维持一个长度为k的窗口,就是说窗口一只向前滑动 11 set.remove((long)nums[i-k]); 12 } 13 set.add((long)nums[i]); 14 } 15 return false; 16 } 17 }