哈希表解决--判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k

今天如期写下昨天看的题目,由于昨晚时间已晚,所以就今晚记录昨晚所学的题目,只是写写自己对题目的理解,借鉴了很多大佬的思想,希望自己由简到难,一步步进步。
题目:
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k
来源:力扣(LeetCode)
在这里记录下符合解题条件的一个解,官网还提供了其余的解题方法。
思路
用散列表来维护这个kk大小的滑动窗口。
算法
在之前的方法中,我们知道了对数时间复杂度的 搜索 操作是不够的。在这个方法里面,我们需要一个支持在常量时间内完成 搜索,删除,插入 操作的数据结构,那就是散列表。这个算法的实现跟方法二几乎是一样的。

遍历数组,对于每个元素做以下操作:
在散列表中搜索当前元素,如果找到了就返回 true。
在散列表中插入当前元素。
如果当前散列表的大小超过了 k, 删除散列表中最旧的元素。
返回 false。

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

整个过程实际上是滑动窗口的思想,首先建立一个哈希表,从数组的第一个数开始遍历,进入循环后,首先判断哈希表中是否存在该数,如果存在就返回true跳出循环,否则就将该数存入哈希表中,哈希表需要设置一个前提就是最多只能保存k个数字,这样才能保证两个数的索引值之差最多为k(因为是先判断再添加进入哈希表中,画图即可理解),所以在加入哈希表之前需要先判断加入之后数量是否大于k,如果大于k,就移除就旧的那个数即可。

需要注意的点就是哈希表中保证只能存有k个元素。

复杂度分析

时间复杂度:O(n)
我们会做 n 次 搜索,删除,插入 操作,每次操作都耗费常数时间。

空间复杂度:O(min(n, k))
开辟的额外空间取决于散列表中存储的元素的个数,也就是滑动窗口的大小 O(min(n,k)),因为也可能还没有存储到k就找到了,所以n可能比k要小。

作者:LeetCode

你可能感兴趣的:(算法,leetcode,java,经验分享)