220.存在重复元素 III

94 阅读1分钟

题目:
给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k **。

如果存在则返回 true,不存在返回 false
解法:
比较差值相关考虑分桶思想。每个桶大小为t + 1(因为需要把0 ~ 9分到一个桶,t需要为10).根据num获取桶的index |index-1|index|index-1| 如果两个数在一个index中,则必然存在abs(nums[i] - nums[j]) <= t,如果在当前桶中没有数,则比较当前的数和相邻桶中存储的数的差值是否 <= t。 index依次增加,并移除i-k及之前的index所在的桶。

func containsNearbyAlmostDuplicate(nums []int, k int, t int) bool {
	slideMap := make(map[int]int)
	for i := 0; i < len(nums); i ++ {
		id := getId(nums[i], t + 1)
		if _, ok := slideMap[id]; ok {
			return true
		}

		if val, ok := slideMap[id + 1]; ok && abs(val, nums[i]) <= t{
			return true
		}

		if val, ok := slideMap[id - 1]; ok && abs(val, nums[i]) <= t{
			return true
		}
		slideMap[id] = nums[i]
		if i >= k {
			delete(slideMap, getId(nums[i - k], t + 1))
		}
	}
	return false
}

func getId(x, w int) int {
        // w = 10 则x=[0,9],[10,19],[20,29]在一个index
        //      index=0, 1, 2
	if x >= 0 {
		return x / w
	}
        // [-1,-9] 的index=0,将index - 1置为index = -1
	return (x / w) - 1
}

func abs(a, b int) int {
	if a > b {
		return a - b
	}
	return b - a
}