我正在研究问题Contains Duplicate III - LeetCode
给出一个整数数组,找出数组中是否存在两个不同的索引 i 和 j ,以使它们之间的绝对差异 nums [i] 和 nums [j] **最多是 t ,而 i 是不同的>和 j 最多为 k 。
示例1:
Input: nums = [1,2,3,1], k = 3, t = 0 Output: true
示例2:
Input: nums = [1,0,1,1], k = 1, t = 2 Output: true
示例3:
Input: nums = [1,5,9,1,5,9], k = 2, t = 3 Output: false
在讨论区中阅读存储桶排序解决方案
class Solution2:
def containsNearbyAlmostDuplicate(self, nums, k, t):
if t < 0: return False
lookup = {}
for i in range(len(nums)):
b_idx = nums[i] // (t+1)
if b_idx in lookup:
return True
if b_idx - 1 in lookup and abs(nums[i] - lookup[b_idx - 1]) < t+1:
return True
if b_idx + 1 in lookup and abs(nums[i] - lookup[b_idx + 1]) < t+1:
return True
lookup[b_idx] = nums[i]
if i >= k: del lookup[nums[i-k] // (t+1)]
return False
说明
这个想法就像存储桶排序算法。假设我们有连续的存储桶,覆盖了num的范围,每个存储桶的宽度为(t + 1)。如果存在两项差异<= t的项目,则将发生以下两项之一:
(1)两个在同一个桶中
(2)邻居桶中的两个
我了解存储桶排序的逻辑,但不知道此解决方案的工作原理。
我认为,有必要在宽度范围内的所有值之间进行比较,但是解决方案仅比较相同的存储桶和相邻的存储桶
del lookup[num[i-k]
,我不知道这种操作的目的。
答案 0 :(得分:4)
第一个问题: 为什么只比较同一桶和相邻桶?
正如作者所说,如果(a, b)
是有效对,有两种情况:
(1)两者位于同一存储桶中
(2)邻居桶中的两个
如果b - a <= t
仅表示上述两种情况,则可以通过此处的存储桶示例来了解它:
之所以使用<-a-- t + 1 --- b-> <----- t + 1 ----->在同一存储桶中
<----- t + 1 --a-> <--- b- t + 1 ----->在邻居桶中
Bucket
是因为我们希望将范围划分为偶数宽度,并减少比较时间。这是一种交换时间的方法。
第二个问题:为什么del lookup[num[i-k]
?
由于第二个限制是差异索引i
,j
最多应为k。
因此,在for i in range(len(nums)):
中,如果是i - j == k
,则应从存储桶中删除先前的索引j。并且包括等于k的差,因此我们应该在逻辑之后删除。
如果您不这样做,则会找到abs(nums[i]-nums[j])<=t
但abs(i-j)>t
我希望我能说清楚,如果您还有其他问题,请发表评论。 :)
顺便提一句建议:如果您感到困惑或困惑,可以通过打印或调试来查看示例,您会更加清楚,尤其是在极端情况下。