220. 存在重复元素 III
难度中等
给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。
示例 1:
输入: nums = [1,2,3,1], k= 3, t = 0 输出: true
示例 2:
输入: nums = [1,0,1,1], k=1, t = 2 输出: true
示例 3:
输入: nums = [1,5,9,1,5,9], k = 2, t = 3 输出: false
题解思路:
首先,定义桶的大小是t+1, nums[i]//(t+1)决定放入几号桶,这样在一个桶里面的任意两个的绝对值差值都<=t例如t=3, nums=[0 ,5, 1, 9, 3,4],那么0号桶就有[0,1,3],1号桶就有[4,5],2号桶就有[9]
先不考虑索引差值最大为K的限制,那么遍历nums每一个元素,并把他们放入相应的桶中,有两种情况会返回True
- 要放入的桶中已经有其他元素了,这时将nums[i]放进去满足差值<=t
- 可能存在前面一个桶的元素并且与nums[i]的差值<=t 或者 存在后面一个桶的元素并且与nums[i]的差值<=t
根据返回True的第一个条件,可以知道前后桶的元素最多也只能有一个。
接着考虑限制桶中的索引差最大为K,当i>=k的时候:
我们就要去删除存放着nums[i-k]的那个桶(编号为nums[i-k]//(t+1)
)
这样就能保证遍历到第i+1
个元素时,全部桶中元素的索引最小值是i-k+1
,就满足题目对索引的限制了
1 class Solution: 2 def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool: 3 if k < 0 or t < 0: 4 return False 5 6 all_buckets = {} 7 bucket_size = t + 1 8 9 for index in range(len(nums)): 10 bucket_num = nums[index] // bucket_size 11 12 if bucket_num in all_buckets: 13 return True 14 15 all_buckets[bucket_num] = nums[index] 16 if (bucket_num-1) in all_buckets and (abs(all_buckets[bucket_num-1]-all_buckets[bucket_num])<=t): 17 return True 18 if (bucket_num+1) in all_buckets and (abs(all_buckets[bucket_num+1]-all_buckets[bucket_num])<=t): 19 return True 20 21 if index>= k: 22 all_buckets.pop(nums[index-k]// bucket_size) 23 24 return False