LeetCode Array 217 219 220 Contains Duplicate I II III

4 篇文章 0 订阅
4 篇文章 0 订阅

217. Contains Duplicate

Given an array of integers, find if the array contains any duplicates.
Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

Example 1:
Input: [1,2,3,1]
Output: true

Example 2:
Input: [1,2,3,4]
Output: false

Example 3:
Input: [1,1,1,3,3,4,3,2,4,2]
Output: true

solution 1: HashSet

    public boolean containsDuplicate(int[] nums) {
        if (nums == null || nums.length <= 1) return false;
        HashSet<Integer> set = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            if (!set.contains(nums[i])) set.add(nums[i]);
            else return true;
        }
        return false;
    }

复杂度:时间空间 O ( n ) O(n) O(n)

solution 2: sort

排序以后,duplicates只能出现在连续的位置上,以此判断是否有duplicates。
复杂度:时间 O ( n l o g n ) O(nlogn) O(nlogn),空间 O ( 1 ) O(1) O(1)

219. Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.

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

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

Example 3:
Input: nums = [1,2,3,1,2,3], k = 2
Output: false

solution 1: HashSet

不仅需要判断有没有duplicates,同时要判断duplicates之间的距离,所以需要保存index和element,采用HashMap,用element作为key,index作为value,因为get(key)函数可以用key得到value。index更容易access,所以不用做key。

    public boolean containsNearbyDuplicate(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k <= 0) return false;
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (!map.containsKey(nums[i])) map.put(nums[i],i);
            else {
                int dist = i - map.get(nums[i]);
                if (dist <= k) return true;
                else map.put(nums[i],i);
            }
        }
        return false;
    }

solution 2:sliding window

建立一个滑动窗口,用set数据结构(HashSet),里面存储一段subarray,且保证窗口大小小于等于k,然后滑动窗口并判断是否有duplicates。

    public boolean containsNearbyDuplicate(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k <= 0) return false;
        HashSet<Integer> set = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            if (set.contains(nums[i])) return true;
            set.add(nums[i]);
           
            if (set.size() > k) set.remove(nums[i-k]);
        }
        return false;
    }

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

solution 1 : sliding window HashSet

采用和上一题相同的方法,但是需要加一个for-each循环用来确定元素值的差小于t。

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

复杂度分析:
时间: O ( n k ) O(nk) O(nk)
空间: O ( k ) O(k) O(k)

solution 2: sliding window TreeSet

采用TreeSet可以降低时间复杂度至 O ( n l o g k ) O(nlogk) O(nlogk)。由于TreeSet底层使用的二叉树,其中存放进去的所有数据都需要排序,要排序,就要求对象具备比较功能。对象所属的类需要实现Comparable接口。或者给TreeSet集合传递一个Comparator接口对象。

    public boolean containsNearbyAlmostDuplicate2(int[] nums, int k, int t) {
        if(nums==null || k<0 || t<0)
            return false;
        TreeSet<Integer> tree = new TreeSet<>();
        for(int i=0; i<nums.length; i++){
            if(i>k)
                tree.remove(nums[i-k-1]);
            Integer ceiling = tree.ceiling(nums[i]);
            Integer floor = tree.floor(nums[i]);
            if(ceiling!=null && (long)ceiling-nums[i]<=t)
                return true;
            if(floor!=null && (long)nums[i]-floor<=t)
                return true;
            tree.add(nums[i]);
        }
        return false;
    }

Note:
需要注意应对overflow的情况:Integer.MAX_VALUE = 2,147,483,647,如果出现nums中两个元素分别使-1,2,147,483,647则会导致overflow,因为 a b s ( 2 , 147 , 483 , 647 − ( − 1 ) ) > I n t e g e r . M A X V A L U E = 2 , 147 , 483 , 647 abs(2,147,483,647-(-1)) > Integer.MAX_VALUE = 2,147,483,647 abs(2,147,483,647(1))>Integer.MAXVALUE=2,147,483,647。为了解决这个问题应该采用Long的数据类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值