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;
    }
} 

原文地址:https://www.cnblogs.com/liuyongyu/p/12509805.html