[Leetcode] Contains Duplicate 包含重复

Contains Duplicate I

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.

集合法

复杂度

时间 O(N) 空间 O(N)

思路

用一个集合记录之前遇到过的数字,如果新的数字已经在集合中出现过了,则说明有重复。

代码

public class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set = new HashSet<Integer>();
        for(int i = 0; i < nums.length; i++){
            if(set.contains(nums[i])) return true;
            set.add(nums[i]);
        }
        return false;
    }
}

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 difference between i and j is at most k.

集合法

复杂度

时间 O(N) 空间 O(K)

思路

同样使用集合,但这次我们要维护集合的大小不超过k,相当于是记录一个宽度为k的窗口中出现过的数字。

代码

public class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Set<Integer> set = new HashSet<Integer>();
        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;
    }
}

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.

二叉搜索树

复杂度

时间 O(NlogK) 空间 O(K)

思路

要求判断之前是否存在差值小于t的数字,我们需要知道在当前数字x两边的数字,即最大的小于x的数字和最小的大于x的数字。二叉搜索树有也有这样的性质,它的左子树的最右节点是最大的较小值,右子树的最左节点是最小的较大值。这里我们用TreeSet这个类,它实现了红黑树,并有集合的性质,非常适合这题。我们同样也是维护一个大小为k的TreeSet,多余k个元素时把最早加入的给删除。用ceiling()和floor()可以找到最小的较大值和最大的较小值。

代码

public class Solution {
    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        TreeSet<Integer> set = new TreeSet<Integer>();
        for(int i = 0; i < nums.length; i++){
            int x = nums[i];
            // 最大的小于x的数字
            if(set.ceiling(x) != null && set.ceiling(x) <= t + x) return true;
            // 最小的大于x的数字
            if(set.floor(x) != null && x <= t + set.floor(x)) return true;
            set.add(x);
            if(set.size()>k) set.remove(nums[i-k]);
        }
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值