1. 问题描述
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.
Input: nums = [1,2,3,1], k = 3
Output: true
Input: nums = [1,0,1,1], k = 1
Output: true
Input: nums = [1,2,3,1,2,3], k = 2
Output: false
给定一个整数数组nums和一个整数k,是否存在i和j使得nums[i]=nums[j],并且i和j的差值小于等于k。
2. 解法1
- 第一步:构造字典,其中key为数组中的值,value为该值对应的id列表;
reverse_nums = {}
for i in range(len(nums)):
if nums[i] in reverse_nums:
reverse_nums[nums[i]].append(i)
else:
reverse_nums[nums[i]] = [i]
- 第二步:针对存在重复值的数组元素,计算元素id间的最小差值,如果小于等于则直接返回True
for key in reverse_nums:
if len(reverse_nums[key]) > 1:
locas = reverse_nums[key]
for i in range(len(locas)-1):
diff = locas[i+1] - locas[i]
if diff <= k:
return True
上述代码中locas = reverse_nums[key]
为取出相应元素的id列表,由于id列表为有序递增列表,所以最小差值必存在于相邻量id之间,当遍历得到的diff小于等于k时,即可返回True。
完整代码如下:
class Solution(object):
def containsNearbyDuplicate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
flag = 0
reverse_nums = {}
for i in range(len(nums)):
if nums[i] in reverse_nums:
reverse_nums[nums[i]].append(i)
else:
reverse_nums[nums[i]] = [i]
for key in reverse_nums:
if len(reverse_nums[key]) > 1:
locas = reverse_nums[key]
min_diff = len(nums)
for i in range(len(locas)-1):
diff = locas[i+1] - locas[i]
if diff <= k:
return True
return False
3. 解法2
在解法1中,我们看到由于在遍历数组时是顺序遍历,且最小差值存在于最相邻的重复元素中,因此在第一步构造字典时,我们无须保存id列表,只要迭代的计算差值即可,所以代码可以修改为如下:
class Solution(object):
def containsNearbyDuplicate(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
if len(nums) == len(set(nums)):
return False
dict_nums = {}
for i in range(len(nums)):
value = nums[i]
if value in dict_nums and i - dict_nums[value] <= k:
return True
dict_nums[value] = i
return False
其中dict_nums字典存放的key是数组元素,value是其对应id,因此遍历到当前的i时,如果nums[i]已经存在于数组中,则表明存在一个重复元素,如果i与dict_nums[value]的差值小于等于k,即表明满足了题中条件,返回True。