zoukankan      html  css  js  c++  java
  • 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 difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.

    链接: http://leetcode.com/problems/contains-duplicate-iii/

    题解:

    一开始的想法是用类似Contains Duplicate II的方法,不过好像不好写。于是研究了一下Discuss,发现有大概三种解法。

    1. Sort the array, keep original index
    2. TreeMap
    3. Bucket sliding window.

    最后暂时只做了第一种方法。排序以后再查找,这里需要自己定义一个数据结构,implements Comparable,并且还有一个inRangeTWith method来比较两个节点的原index是否在t范围内。  二刷一定要补上第二和第三种。

    Time Complexity - O(n2) , Space Complexity - O(n)

    public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            if(nums == null || nums.length < 2 || t < 0 || k < 0)
                return false;
            
            ValueWithIndex[] arr = new ValueWithIndex[nums.length];
            for(int i = 0; i < nums.length; i++)
                arr[i] = new ValueWithIndex(nums[i], i);
            
            Arrays.sort(arr);
            
            for(int i = 0; i < arr.length; i++) {
                for(int j = i + 1; (j < arr.length) && (arr[j].inRangeTWith(arr[i], t)); j++) {
                    if(Math.abs(arr[i].index - arr[j].index) <= k)
                        return true;
                }
            }
            return false;
        }
        
        private class ValueWithIndex implements Comparable<ValueWithIndex> {
            public int value;
            public int index; 
            
            public ValueWithIndex(int val, int i) {
                this.value = val;
                this.index = i;
            }
            
            public int compareTo(ValueWithIndex v2) {
                if(value < 0 && v2.value >= 0)
                    return -1;
                if(value >= 0 && v2.value < 0)
                    return 1;
                return value - v2.value;
            }
            
            public boolean inRangeTWith(ValueWithIndex v2, int t) { // value always >= v2.value
                if(value == v2.value)
                    return true;
                if(value >= 0 && v2.value >= 0)
                    return value - v2.value <= t;
                else if(value < 0 && v2.value < 0)
                    return value <= v2.value + t;
                else
                    return value - t <= v2.value;
            }
        }
    }

    二刷:

    Java:

    使用类似Contains Duplicates II的方法。 Time Complexity - O(n ^ 2) TLE, Space Complexity - O(n)

    public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            if (nums == null || nums.length < 2) return false;
            Set<Integer> set = new HashSet<>();
            
            for (int i = 0; i < nums.length; i++) {
                for (int num : set) {
                    if (Math.abs(num - nums[i]) <= t) return true;
                }
                set.add(nums[i]);
                if (i >= k - 1) set.remove(i - k + 1);
            }
            return false;
        }
    }

    新建数据结构先排序再查找。

    1. 这里我们先构建一个Node class包含val和index
    2. 根据数组,用nums[i]和i作为pair创建Node数组
    3. 对Node数组使用nums[i]进行排序
    4. 使用sliding window进行比较,这个部分比较的复杂度其实是O(n)

    要注意我们的Node class继承了Comparable<Node> interface, 注意写compareTo() 和 inRangeTWith() 这两个方法时的一些边界条件地处理。

    Time Complexity - O(nlogn) , Space Complexity - O(n)

    public class Solution {
        public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
            if (nums == null || nums.length < 2 || t < 0 || k < 0) return false;
            int len = nums.length;
            Node[] nodes = new Node[len];
            for (int i = 0; i < len; i++) nodes[i] = new Node(nums[i], i);
            Arrays.sort(nodes);
            
            for (int i = 0; i < len; i++) {
                for (int j = i + 1; (j < len) && (nodes[j].inRangeTWith(nodes[i], t)); j++) {
                    if (Math.abs(nodes[i].index - nodes[j].index) <= k) return true;
                }
            }
            return false;
        }
        
        private class Node implements Comparable<Node> {
            public int val;
            public int index; 
            
            public Node(int val, int i) {
                this.val = val;
                this.index = i;
            }
            
            public int compareTo(Node n2) {
                if (val < 0 && n2.val >= 0) return -1;
                if (val >= 0 && n2.val < 0) return 1;
                return val - n2.val;
            }
            
            public boolean inRangeTWith(Node n2, int t) { // value always >= v2.value
                if(val == n2.val) return true;
                if((val >= 0 && n2.val >= 0) || (val < 0 && n2.val < 0)) {
                    return val - n2.val <= t;
                } else {
                    return val <= n2.val - t;
                }
                    
            }
        }
    }

    Reference:

    https://leetcode.com/discuss/65056/java-python-one-pass-solution-o-n-time-o-n-space-using-buckets

    https://leetcode.com/discuss/47974/java-treeset-implementation-nlogk

    https://leetcode.com/discuss/52545/java-solution-without-dictionary-sort-nums-record-positions

    https://leetcode.com/discuss/39216/ac-short-java-solution-using-treeset-and-subset-function

    https://leetcode.com/discuss/38206/ac-o-n-solution-in-java-using-buckets-with-explanation

    https://leetcode.com/discuss/38177/java-o-n-lg-k-solution

    https://leetcode.com/discuss/38148/my-o-n-accepted-java-solution-using-hashmap

    https://leetcode.com/discuss/38146/java-solution-with-treeset

  • 相关阅读:
    奶萨的团队框架(Grid)个人设置技巧以及使用方法
    巫妖王之怒:3.35暗牧输出手法入门指引
    WLK3.3.5治疗怎么玩:治疗职业心得汇总
    WLK奥术fs怎么打高DPS
    战斗贼入门级输出循环
    3.35国服法师DPS提升指引 奥与火的双重奏
    3.35奶萨新手无聊看看帖
    邪冰双手(鲜血领域)——新手推荐,AOE和移动战都不错
    WLK 防骑T
    WLK防骑拉怪手法(要有序排列再给我答案)
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4990420.html
Copyright © 2011-2022 走看看