220.contains-duplicate-iii.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. import (
  2. "math"
  3. )
  4. func containsNearbyAlmostDuplicate(nums []int, k int, t int) bool {
  5. if t < 0 || k <= 0 {
  6. return false
  7. }
  8. // Bucket sort. |a - b| <= t => |a/t - b/t| <= 1 => |floor(a/t) - floor(b/t)| <= 1,
  9. // we use t to split the nums into several buckets. Given key = floor(nums[i]/t), then
  10. // next number which meets the condiction is in [key-1, key+1].
  11. // When key1 == key2, the condiction is met; if |key1 - key2| == 1, we have to double
  12. // check the condiction is met or not. Maintain a k length map to ensure |i - j| <= k.
  13. bucket := make(map[int]int)
  14. gap := t
  15. if gap == 0 {
  16. gap = 1
  17. }
  18. for i := range nums {
  19. key := int(math.Floor(float64(nums[i]) / float64(gap))) // Return the floor of x/y
  20. if _, ok := bucket[key]; ok {
  21. return true
  22. }
  23. if n, ok := bucket[key-1]; ok && abs(nums[i]-n) <= t {
  24. return true
  25. }
  26. if n, ok := bucket[key+1]; ok && abs(nums[i]-n) <= t {
  27. return true
  28. }
  29. bucket[key] = nums[i]
  30. if k <= i {
  31. delete(bucket, nums[i-k]/gap)
  32. }
  33. }
  34. return false
  35. }
  36. func abs(x int) int {
  37. if x < 0 {
  38. return -x
  39. }
  40. return x
  41. }