dengxinyi 6 years ago
parent
commit
83b8994014
1 changed files with 34 additions and 22 deletions
  1. 34 22
      medium/220.contains-duplicate-iii.go

+ 34 - 22
medium/220.contains-duplicate-iii.go

@@ -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
 }