220. Contains Duplicate III

一、题目

  1、审题

  

  2、分析

    判断数组中是否存在两个元素之差在 t 之内,且此两个元素下标之差在 k 之内。

 

二、解答

  1、思路:

    方法一、

      桶排序

    ①、采用 Map ,key 记录桶的序号,value 记录元素的值。每个桶的元素个数为 t + 1, eg t=3,则桶大小为 4, 元素 0、1、2、3 在一个桶,桶元素最大差值为 3 - 0 = 3 <= t 。

    ②、由于存在 (t + 1, -t -1) 都存在于桶序号为 0 的同一个桶,为了消除这个错误,将元素化为 Long,且值均大于 0。做法是 key 用  nums[i] - Integer.MIN_VALUE 表示。

    ③、若遍历的连续的 k 个元素中出现在同一个桶情况,则返回 true,若有连续桶,则比较这两个元素值。

    ④、当桶数大于 k 了,则去除最早添加的一个桶,添加新的遍历的元素的 entry。

 1     public boolean containsNearbyAlmostDuplicate2(int[] nums, int k, int t) {
 2         
 3         if(k < 1 || t < 0)
 4             return false;
 5         
 6         HashMap<Long, Long> map = new HashMap<>();
 7         for (int i = 0; i < nums.length; i++) {
 8             // Integer 范围是 [-2147483648, 2147483647]
 9             // nums[i] - Integer.MIN_VALUE 使得所有数值均  >= 0, 否则  (t+1, -t-1) 均在 0 这个桶内  
10             long remappendNum = (long) nums[i] - Integer.MIN_VALUE;
11             long bucket = remappendNum / ((long)t + 1);
12             if(map.containsKey(bucket)
13                 ||    (map.containsKey(bucket - 1) && remappendNum - map.get(bucket - 1) <= t)
14                     || (map.containsKey(bucket + 1) && map.get(bucket + 1) - remappendNum <= t))
15                     return true;
16             
17             if(map.entrySet().size() >= k) {
18                 long lastBucket = ((long) nums[i - k] - Integer.MIN_VALUE) / ((long)t + 1);
19                 map.remove(lastBucket);
20             }
21             map.put(bucket, remappendNum);
22         }
23         return false;
24     }

 

  方法二、

    采用 TreeSet

    注意将 Integer 转为 Long 型进行比较,避免溢出情况。

 1 // TreeSet 继承自 NavigableSet,NavigableSet 提供导航方法:
 2     /*
 3      *  1、 lower(e): 返回 小于 给定值的元素
 4      *  2、floor(e): 小于等于
 5      *  3、ceiling(e): 大于等于
 6      *  4、higher(e): 大于
 7      */
 8     public boolean containsNearbyAlmostDuplicate3(int[] nums, int k, int t) {
 9         
10         if(k < 1 || t < 0)
11             return false;
12         
13         TreeSet<Long> values = new TreeSet<>();
14         for (int i = 0; i < nums.length; i++) {
15             long num = nums[i];    // 转为 Long 型,避免了整形溢出情况。
16             Long floor = values.floor(num + t); // 小于等于
17             Long ceil = values.ceiling(num - t); // 大于等于
18             if((floor != null && floor >= num)
19                     || (ceil != null && ceil <= num))
20                 return true;
21             
22             values.add(num);
23             if(i >= k)
24                 values.remove((long)(nums[i - k]));
25         }
26         return false;
27     }

 

posted @ 2018-11-03 22:23  skillking2  阅读(136)  评论(0编辑  收藏  举报