zoukankan      html  css  js  c++  java
  • 220. Contains Duplicate III

    这个和 I 、II 比不是一个级别的。。

    I找数组里有没有重复的,用HashSet判定就行。

    II是有没有重复,然后重复俩元素距离小于K。
    用HashTable,KEY是元素,VALUE是坐标,遍历数组遇到存在于TABLE中的元素,返还那个元素的坐标,和当前比较,如果小于K,就TRUE;否则用当前元素的坐标替换原来的VALUE,保留最近的,如果最近的都大于K,那么之前的那些肯定更大于K。。

    III,难度陡然上升。。。

    用TreeSet,其中2个方程比较关键
    1 floor(n)返还不小于n的最小元素
    2 ceiling(n)返还不大于n的最大元素

    TreeSet是滑动的窗口,里面是满足距离小于k的所有元素。

    比如K是4 那么
    8 1 2 3 4 9 5
    ——————————
    ——————————
    ————————————

    横线就是窗口的变化

    遍历到4的时候从 8 1 2 3里面找
    遍历到9的时候从 1 2 3 4里面找
    遍历到5的时候从 2 3 4 9里面找

    找到时候因为所有值都满足K的要求,那么就看T就行了。

    正常情况是遍历窗口里所有元素m,然后
    Math.abs(m-nums[n]) <= t)
    但是超时。然后我们只比较
    大于当前元素里最小的 floor(nums[n]) - nums[n] <= t
    小于当前元素里最大的 nums[n] - ceiling(nums[n]) <= t

    有一个满足就RETURN TRUE

    否则当前元素进入窗口。
    然后如果窗口大于K,把第一个元素拿出去。。

    //difference between i and j is at most k
            //nums[i] and nums[j] is at most t
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) 
        {
            //if(nums.length < 2) return false;
            if(k <= 0) return false;
            if(t < 0) return false;
            //if(t == 0) return false;
    
            TreeSet<Long> set = new TreeSet<Long>();
    
            for(int n = 0; n < nums.length;n++)
            {
                Long tempVal = new Long(nums[n]);
    
                if( (set.floor(tempVal) != null && tempVal - set.floor(tempVal) <= new Long(t))  ||
                (set.ceiling(tempVal) != null && set.ceiling(tempVal) - tempVal <= new Long(t)   )  )return true;
    
                set.add(tempVal);
                if(n >= k) set.remove(new Long(nums[n-k]));
            }
    
            return false;
        }
    
    

    好鸡巴难。。

    判定RETURN TRUE的2个情况,用||可以通过,换成2个IF xxx renturn true;
    if xxx return true;
    超时,醉了。。

    然后EDGE CASE,K < 1 FALSE 因为距离必须大于1,0的话就是相同元素,不满足distinct。小于0的话就很无聊,没有负距离,感觉这种EDGE CASE是为了测验而测验,这个题的精髓明显是前面的逻辑关系。。

    另一个EDGE CASE T < 0一样,绝对值不能小于0。。这俩EDGE CASE毁了好心情。。


    二刷。

    这个傻逼题。。

    Edge cases太多了。

    维持滑窗,滑窗用treeSet这个数据结构,主要为了lgN时间找到需要的2个边界值。

    不小于Target的最小值;
    不大于Target的最大值。。

    Time: O(n lg K)
    Space: O(k)

    public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            if (k <= 0) return false;
            if (t < 0) return false;
            
            TreeSet<Long> window = new TreeSet<>();
            
            for (int i = 0; i < nums.length; i++) {
                
                long temp = (long)nums[i];
                    
                if (window.floor(temp) != null && temp - window.floor(temp) <= (long)t) {
                    return true;
                }
                    
                if (window.ceiling(temp) != null && window.ceiling(temp) - temp <= (long)t) {
                    return true;
                }
                    
                window.add(temp);
                if (i >= k) {
                    window.remove((long)nums[i - k]);
                }
            }
            return false;
        }
    }
    

    另一种做法是排序,然后用个MAP之类的记录INDEX。。。

    比较复杂,而且有多余空间。

  • 相关阅读:
    Stone Game, Why are you always there? HDU
    SG函数
    A New Stone Game POJ
    卡特兰数
    找单词 HDU
    排列组合 HDU
    Harry And Magic Box HDU
    GCD and LCM HDU
    Co-prime HDU
    线段树——F
  • 原文地址:https://www.cnblogs.com/reboot329/p/6158936.html
Copyright © 2011-2022 走看看