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。。。

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

  • 相关阅读:
    hdu 2485 Destroying the bus stations 迭代加深搜索
    hdu 2487 Ugly Windows 模拟
    hdu 2492 Ping pong 线段树
    hdu 1059 Dividing 多重背包
    hdu 3315 My Brute 费用流,费用最小且代价最小
    第四天 下载网络图片显示
    第三天 单元测试和数据库操作
    第二天 布局文件
    第一天 安卓简介
    Android 获取存储空间
  • 原文地址:https://www.cnblogs.com/reboot329/p/6158936.html
Copyright © 2011-2022 走看看