|
@@ -1,32 +1,44 @@
|
|
|
+import (
|
|
|
+ "math"
|
|
|
+)
|
|
|
+
|
|
|
func containsNearbyAlmostDuplicate(nums []int, k int, t int) bool {
|
|
|
- mq := NewMagicQueue(k + 1)
|
|
|
+ if t < 0 || k <= 0 {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ // Bucket sort. |a - b| <= t => |a/t - b/t| <= 1 => |floor(a/t) - floor(b/t)| <= 1,
|
|
|
+ // we use t to split the nums into several buckets. Given key = floor(nums[i]/t), then
|
|
|
+ // next number which meets the condiction is in [key-1, key+1].
|
|
|
+ // When key1 == key2, the condiction is met; if |key1 - key2| == 1, we have to double
|
|
|
+ // check the condiction is met or not. Maintain a k length map to ensure |i - j| <= k.
|
|
|
+ bucket := make(map[int]int)
|
|
|
+ gap := t
|
|
|
+ if gap == 0 {
|
|
|
+ gap = 1
|
|
|
+ }
|
|
|
for i := range nums {
|
|
|
- mq.Enqueue(nums[i])
|
|
|
- if mq.MinGap() <= t {
|
|
|
+ key := int(math.Floor(float64(nums[i]) / float64(gap))) // Return the floor of x/y
|
|
|
+ if _, ok := bucket[key]; ok {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ if n, ok := bucket[key-1]; ok && abs(nums[i]-n) <= t {
|
|
|
return true
|
|
|
}
|
|
|
+ if n, ok := bucket[key+1]; ok && abs(nums[i]-n) <= t {
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ bucket[key] = nums[i]
|
|
|
+ if k <= i {
|
|
|
+ delete(bucket, nums[i-k]/gap)
|
|
|
+ }
|
|
|
}
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-type MagicQueue struct {
|
|
|
- Size int
|
|
|
- MQ []int
|
|
|
-}
|
|
|
-
|
|
|
-func NewMagicQueue(size int) MagicQueue {
|
|
|
- return MagicQueue{size, make([]int, 0)}
|
|
|
-}
|
|
|
-
|
|
|
-func (mq MagicQueue) MinGap() int {
|
|
|
- return 0
|
|
|
-}
|
|
|
-
|
|
|
-func (mq MagicQueue) Len() int {
|
|
|
- return len(mq.MQ)
|
|
|
-}
|
|
|
-
|
|
|
-func (mq *MagicQueue) Enqueue(x int) {
|
|
|
-
|
|
|
+func abs(x int) int {
|
|
|
+ if x < 0 {
|
|
|
+ return -x
|
|
|
+ }
|
|
|
+ return x
|
|
|
}
|
|
|
|