leetcode220
Contains Duplicate III
package leetcode; import java.util.TreeMap; public class Solution220 extends Solution { @Override public void test() { int[] nums = {0,10,22,15,0,5,22,12,1,5}; int k = 3, t = 3; // int[] nums = {3,6,0,2}; // int k = 2, t = 2; System.out.println(containsNearbyAlmostDuplicate(nums, k, t)); //二分法 // time limit exception System.out.println(helper2(nums, k, t)); // 使用treeMap //AC } public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { return helper(nums, 0, nums.length - 1, k, t); } /* 使用合并排序的思想,对nums进行二分,然后合并时比较两个部分的连接处是否满足条件:Math.abs(nums[i]-nums[j]) < t && i - j < k 结果:out time limit */ private boolean helper(int[] nums, int start, int end, int k, int t){ if(start >= end) return false; int mid = start + (end - start) / 2; if (helper(nums, start, mid, k, t)) { return true; } if (helper(nums, mid+1, end, k, t)) { return true; } return isExists(nums, mid + 1, mid + k <= end ? mid + k : end, k, t); } private boolean isExists(int[] nums, int start, int end, int k, int t){ for(int i = start; i<=end; i++){ int j = i - k < 0 ? 0 : i - k; while(j < i){ if(Math.abs((long) nums[i] - (long) nums[j]) <= t){ return true; } j++; } } return false; } /* 借助TreeMap的方法--ceilingKey()和floorKey(),快速确定滑动当前值所需要的范围。 假设 遍历nums,index = i; 当t==0时,也就是说需要找到之前数组中一个与当前数值nums[i]相同的值,直接查看map中是否有满足条件的值; 当t!=0时,借助TreeMap的两个方法,可以快速的定位当前值nums[i]满足题干要求的范围(-t <= nums[i] - x <= t)且在map存在的值,x属于[l, h], 其中,l是在map中满足大于nums[i]-t的最小值,h是在map中满足小于nums[i]+t的最大值,然后判断l和h对于nums[i]是否满足条件(<=t) */ private boolean helper2(int[] nums, int k ,int t){ if(nums.length < 1 || k < 1 || t < 0) return false; TreeMap<Long, Integer> map = new TreeMap<>(); map.put((long) nums[0], 0); for(int i=1; i<nums.length; i++){ long num = (long) nums[i]; if(t == 0){ if (map.containsKey(num) && i - map.get(num) <= k) { return true; } map.put(num, i); }else { Long l = map.ceilingKey(num - (long) t); Long h = map.floorKey(num + (long) t) ; if(l != null && h != null && (Math.abs(num - l) <= t|| Math.abs(num - h) <= t)) { int left = map.get(l); int right = map.get(h); if(i - left <= k || i - right <= k){ return true; } } map.put(num, i); } } return false; } }