查找表+滑动窗口

例题:存在重复元素II

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

·ij差的绝对值至多为k的话,那么可以使用一个大小固定为k+1的滑动窗口,只要这个窗口内有重复的元素,那就说明符合题意,返回true。如果遍历完都找不到,返回false。
由于不需要统计次数,所以使用set即可。

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        if(nums.length==0) return false;
        int l = 0;
        int r = nums.length<k+1?nums.length-1:k;
        Set<Integer> set = new HashSet<Integer>();
        for(int i=0;i<=r;i++){
            if(set.contains(nums[i])) return true;
            set.add(nums[i]);
        }
        while(r<nums.length-1){
            set.remove(nums[l]);
            if(set.contains(nums[r+1])) return true;
            set.add(nums[r+1]);
            l++;
            r++;
        }
        return false;
    }
}

1.存在重复元素

给定一个整数数组,判断是否存在重复元素。

如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

这比例题还简单,直接滑动窗口都省了,一直遍历即可。

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;
    }
}

2.存在重复元素III

给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ

思路:桶排序
桶排序的思路就是先将所有元素放到一个一个桶里,比如说[0,9],[10,19],[20,29],[30,39],[40,49] 这样的,然后再对每一个同中的元素进行排序。

那么这个题呢就不用排序了,但我们可以建造多个大小为t+1的桶,来存储滑动窗口中的数字。
每次滑动窗口遍历到一个新的数字,就先判断它应该放到哪个桶里,使用方法getId(),得到桶号之后判断:

  • 如果桶中有一个元素了,那么说明找到了,返回true;
  • 没有则判断附近两个桶中是否有元素,有则判断是否相减小于t+1,是则返回true;
  • 否则就把它放到这个桶里

一直到遍历完都没有找到的话就返回false。
由于每个桶最多只能有一个元素,所以只需要将桶号保存在一个Map中即可,key为桶号,value为桶中元素的值

public class Solution {
    // In Java, `-3 / 5 = 0` and but we need `-3 / 5 = -1`.
    private long getID(long x, long w) {
        return x < 0 ? (x + 1) / w - 1 : x / w;
    }

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        if (t < 0) return false;
        Map<Long, Long> d = new HashMap<>();
        long w = (long)t + 1;
        for (int i = 0; i < nums.length; ++i) {
            long m = getID(nums[i], w);
            // check if bucket m is empty, each bucket may contain at most one element
            if (d.containsKey(m))
                return true;
            // check the nei***or buckets for almost duplicate
            if (d.containsKey(m - 1) && Math.abs(nums[i] - d.get(m - 1)) < w)
                return true;
            if (d.containsKey(m + 1) && Math.abs(nums[i] - d.get(m + 1)) < w)
                return true;
            // now bucket m is empty and no almost duplicate in nei***or buckets
            d.put(m, (long)nums[i]);
            //只使用一个下标便可以控制滑动窗口,学到了
            if (i >= k) d.remove(getID(nums[i - k], w));
        }
        return false;
    }
}
发布了60 篇原创文章 · 获赞 6 · 访问量 1201

猜你喜欢

转载自blog.csdn.net/DLC990319/article/details/105103622
今日推荐