• 220. 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 absolute difference between nums[i] and nums[j] is at most t and the absolute difference between i and j is at most k.

    Example 1:

    Input: nums = [1,2,3,1], k = 3, t = 0
    Output: true
    

    Example 2:

    Input: nums = [1,0,1,1], k = 1, t = 2
    Output: true
    

    Example 3:

    Input: nums = [1,5,9,1,5,9], k = 2, t = 3
    Output: false

    1. brute force
    注意里面有用到long,因为可能会有边界条件:
    [-1,2147483647]
    1
    2147483647
    而 2147483647 + 1 = -2147483648
    class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            Map<Integer, HashSet<Integer>> map = new HashMap();
            int le = nums.length;
            for(int i = 0; i < le; i++){
                for(int j = i + 1; j < le; j++){
                    long abs = Math.abs((long)nums[j] - (long)nums[i]);
                    if(abs <= t){
                        if(j - i <= k){
                            System.out.println(abs);
                            return true;
                        }                    
                    }                
                }
            }
            return false;
        }
    }

    2. 桶排序,具体看讲解

     public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            if (k < 1 || t < 0) return false;
            Map<Long, Long> map = new HashMap<>();
            for (int i = 0; i < nums.length; i++) {
                long remappedNum = (long) nums[i] - Integer.MIN_VALUE;
                long bucket = remappedNum / ((long) t + 1);
                if (map.containsKey(bucket)
                        || (map.containsKey(bucket - 1) && remappedNum - map.get(bucket - 1) <= t)
                            || (map.containsKey(bucket + 1) && map.get(bucket + 1) - remappedNum <= t))
                                return true;
                if (map.entrySet().size() >= k) {
                    long lastBucket = ((long) nums[i - k] - Integer.MIN_VALUE) / ((long) t + 1);
                    map.remove(lastBucket);
                }
                map.put(bucket, remappedNum);
            }
            return false;
        }
    }

    大概意思是因为两数最大差是t,就把桶的容量设为t+1,例如[0,1,2,3,4], t = 2,桶0【0,1,2】,桶1【3,4】,而且可以避免t==0的以t为桶容量时候除以0

    最开始要remap所有的数,避免负数情况以及Integer.MAX_VALUE == 2^31 - 1的情况,很狗,所以下面所有的数都变成long.

    如果两数在一个桶里(通过map.containsKey()实现,说明两数之差小于t),但也要注意相邻桶的状况,比如2和3也只差1<t==2, 说明我们也要判断一下左边右边桶里的数。!!!看到这才发现,每只桶里一直最多只有1个元素(这样才能比较)

    --》最后是if (map.entrySet().size() >= k) ,这个是因为两个index不能超过k,那为啥这么实现?因为我们index是i,从0到k-1一直相安无事,直到i > =k,就像一个window.然后因为我们是先判断后put,最终会维持map size为k

    很巧妙的方法,但也用了很多时间读懂,还要提高

  • 相关阅读:
    .NetCore 导出Execl
    10块钱可以喝几瓶?
    menuStrip鼠标滑过自动弹出
    静态变量
    DataTable.SELECT日期类型筛选处理
    Java中accept()阻塞是如何实现的
    L1正则在0处不可导怎么办?
    L1和L2正则化原理推导.md
    5局3胜和3局2胜哪个更容易赢.md
    Java集合(一): 集合框架Collection和Map
  • 原文地址:https://www.cnblogs.com/wentiliangkaihua/p/13191133.html
Copyright © 2020-2023  润新知