220. Contains Duplicate III
来源:互联网 发布:卖跑步装备的淘宝店 编辑:程序博客网 时间:2024/06/05 11:29
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小的时候在index<=K范围内检测是否有和当前元素相差t 以内(临近)的元素,K大的时候以当前元素正负t为范围在hashmap扫描是否重复。
这思路有些投机取巧的意思。
public static boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t){int len=nums.length;if(len<=1)return false;HashMap<Integer, Integer> hashmap=new HashMap<>(len);for(int i=0;i<len;i++){long num=nums[i];if(k<=100)for(int m=Math.max(i-k,0);m<i;m++){long prenum=hashmap.get(m);if(prenum>=num-t&&prenum<=num+t)return true;}else{for(long m=num-t;m<=num+t;m++)if(hashmap.containsKey(m)&&i-hashmap.get(m)<=k)return true;}hashmap.put(i, (int) num);}return false;}
更好的方法,摘自
https://discuss.leetcode.com/topic/15199/ac-o-n-solution-in-java-using-buckets-with-explanation
https://discuss.leetcode.com/topic/15191/java-o-n-lg-k-solution
-------------------------------------------------------------------------------------------------------------------------
As a followup question, it naturally also requires maintaining a window of size k. When t == 0, it reduces to the previous question so we just reuse the solution.
Since there is now a constraint on the range of the values of the elements to be considered duplicates, it reminds us of doing a range check which is implemented in tree data structure and would take O(LogN) if a balanced tree structure is used, or doing a bucket check which is constant time. We shall just discuss the idea using bucket here.
Bucketing means we map a range of values to the a bucket. For example, if the bucket size is 3, we consider 0, 1, 2 all map to the same bucket. However, if t == 3, (0, 3) is a considered duplicates but does not map to the same bucket. This is fine since we are checking the buckets immediately before and after as well. So, as a rule of thumb, just make sure the size of the bucket is reasonable such that elements having the same bucket is immediately considered duplicates or duplicates must lie within adjacent buckets. So this actually gives us a range of possible bucket size, i.e. t and t + 1. We just choose it to be t and a bucket mapping to be num / t.
Another complication is that negative ints are allowed. A simple num / t just shrinks everything towards 0. Therefore, we can just reposition every element to start from Integer.MIN_VALUE.
public class Solution { public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { if (k < 1 || t < 0) return false; Map<Long, Long> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { long remappedNum = (long) nums[i] - Integer.MIN_VALUE; long bucket = remappedNum / ((long) t + 1); if (map.containsKey(bucket) || (map.containsKey(bucket - 1) && remappedNum - map.get(bucket - 1) <= t) || (map.containsKey(bucket + 1) && map.get(bucket + 1) - remappedNum <= t)) return true; if (map.entrySet().size() >= k) { long lastBucket = ((long) nums[i - k] - Integer.MIN_VALUE) / ((long) t + 1); map.remove(lastBucket); } map.put(bucket, remappedNum); } return false; }}
Edits:
Actually, we can use t + 1 as the bucket size to get rid of the case when t == 0. It simplifies the code. The above code is therefore the updated version.
-----------------------------------------------------------------------------------------------------
This problem requires to maintain a window of size k of the previous values that can be queried for value ranges. The best data structure to do that is Binary Search Tree. As a result maintaining the tree of size k will result in time complexity O(N lg K). In order to check if there exists any value of range abs(nums[i] - nums[j]) to simple queries can be executed both of time complexity O(lg K)
Here is the whole solution using TreeMap.
public class Solution { public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { if (nums == null || nums.length == 0 || k <= 0) { return false; } final TreeSet<Integer> values = new TreeSet<>(); for (int ind = 0; ind < nums.length; ind++) { final Integer floor = values.floor(nums[ind] + t); final Integer ceil = values.ceiling(nums[ind] - t); if ((floor != null && floor >= nums[ind]) || (ceil != null && ceil <= nums[ind])) { return true; } values.add(nums[ind]); if (ind >= k) { values.remove(nums[ind - k]); } } return false; }}
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 220. Contains Duplicate III
- 软件开发者如何准备未来?
- MongoDB学习整理
- 3. ioctl
- java基础(七)/面向对像
- 长逻辑运算符和短逻辑运算符
- 220. Contains Duplicate III
- 原始套接字编程(1)
- matlab-线性代数 创建N阶单位矩阵
- coreeek 和 sphinx 的配置与使用
- 打卡阅读
- 【读书笔记】Zygote 和 System 进程的启动过程
- VS2012 将两个项目合并在一个项目中使用
- matlab-线性代数 创建对角矩阵
- 下载的asp源码怎么使用?