• LeetCode | Contains Duplicate III


    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.

    要求:|nums[i]-nums[j]|<=t,且|i-j|<=k,用hashmap就没意义了,因为不是找相同,而是找相近了。
    tag提示binary search tree,而java中的tree容器有:TreeSet与TreeMap。其中,TreeSet是基于TreeMap实现的,底层使用红黑树,属于平衡二叉树。TreeSet保证基本操作(add,remove,contains)时间复杂度为O(logn),且内部元素有序。(hashmap不保证有序,且两次返回的顺序也不一定相同,但是它对于get与put操作能保证constant-time performance)


    TreeSet<E>中的一些方法:(注意TreeSet中的元素时有序的)
    ceiling(E e):大于等于e中的最小值
    floor(E e):  小于等于e中的最大值
    higher(E e)/lower(E e):大于/小于 e中的 最小/最大 的元素
    first():     返回最小的元素
    last():      返回最大的元素

    正确的代码:

    public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            
            if(k<1 || t<0){
                return false;
            }
            
            boolean result = false;
            TreeSet<Integer> mySet = new TreeSet<Integer>();
            
            for(int i=0; i<nums.length; i++){
                Integer high = mySet.ceiling(nums[i]);      //大于等于nums[i]的最小值
                Integer low = mySet.floor(nums[i]);         //小于等于nums[i]的最大值
                if(high!=null && high<=t+nums[i] || low!=null && nums[i]<=t+low){
                    result = true;
                    break;
                }
                mySet.add(nums[i]);
                if(i>=k){                                  //使set的大小始终小于等于k,起到滑动窗口的作用
                    mySet.remove(nums[i-k]);
                }
                
            }
            
            return result;
        }
    }
    注意,在上面的代码中:
    if(high!=null && high-nums[i]<=t || low!=null && nums[i]-low<=t){
        result = true;
        break;
    }
    这样的写法不行,leetcode有个testcase是[-1,2147483647], 1, 2147483647。按上面的写法会发生溢出。。。



    下面是有错的代码:(用map< nums[i], index >来记录已遍历过的值及其index,这种想法是可行的,但在本题的条件下,就得额外考虑一些东西了)

    public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            
            if(k<1 || t<0){
                return false;
            }
            
            boolean result = false;
            TreeMap<Integer, Integer> myMap = new TreeMap<Integer, Integer>();
                                                            //找了很久,终于找到这段代码哪里错了。。。。
            for(int i=0; i<nums.length; i++){               //[10,100,11,9],k=1,t=2,当循环到num[3]=9时,得low=null,high=<10,0>
                Integer high = myMap.ceilingKey(nums[i]);   //而非<11,2>,代码判断t满足,但是k不满足,从而result=false...
                Integer low  = myMap.floorKey(nums[i]);     
                if(high!=null && high<=t+nums[i] && i-myMap.get(high)<=k){
                    result = true;                          //故在上面的情况下,仅仅找到一个high就判断当前遍历的nums[i]能否返回true是不够的
                    break;                                  //还要找到比high大的最小元素再判断,然后循环找下去,甚至当对元素间距k要求很松时,
                }                                           //可能得在map中找到所有比nums[i]大的元素判断
                if(low!=null && nums[i]<=t+low && i-myMap.get(low)<=k){
                    result = true;
                    break;
                }
                
                myMap.put(nums[i], i);
            }
            
            return result;
        }
    }


  • 相关阅读:
    【LOJ】#2071. 「JSOI2016」最佳团体
    【LOJ】#2070. 「SDOI2016」平凡的骰子
    【LOJ】#2069. 「SDOI2016」齿轮
    【LOJ】#2068. 「SDOI2016」探险路线
    【LOJ】#2067. 「SDOI2016」硬币游戏
    【LOJ】#2066. 「SDOI2016」墙上的句子
    【LOJ】#2065. 「SDOI2016」模式字符串
    【LOJ】#2064. 「HAOI2016」找相同字符
    【LOJ】#2063. 「HAOI2016」字符合并
    【LOJ】#2062. 「HAOI2016」地图
  • 原文地址:https://www.cnblogs.com/dosmile/p/6444422.html
Copyright © 2020-2023  润新知