题目:
给你一个整数数组 nums 和一个整数 k,请你在数组中找出 不同的 k-diff 数对,并返回不同的 k-diff 数对 的数目。
k-diff 数对定义为一个整数对 (nums[i], nums[j]) ****,并满足下述全部条件:
0 <= i, j < nums.lengthi != jnums[i] - nums[j] == k
注意,|val| 表示 val 的绝对值。
算法:
方法一:hash 表
这种朴素方法都想不出来了吗
时间复杂度,空间复杂度O(n)
func findPairs(nums []int, k int) int {
count := 0
numCount := make(map[int]int)
for i := range nums {
numCount[nums[i]] ++
}
for num,c := range numCount {
if k == 0 {
if c > 1 {
count ++
}
} else {
if numCount[num - k] > 0 {
count ++
}
if numCount[num + k] > 0 {
count ++
}
}
numCount[num] = 0
}
return count
}
方法二:hash table + 二分
目的是用数组替代map,减少内存的使用 。
数组代替map,一个去重保存元素(list),一个保存元素和在nums中的出现次数。
可以看到内存使用确实好不少。
时间复杂度:O(n) + O(n) + ?
时间复杂度O(n)
func findPairs(nums []int, k int) int {
count := 0
// list数组有序保存去重之后的nums
sort.Ints(nums)
list := make([]int, 0)
for i := range nums {
if len(list) == 0 || list[len(list) - 1] != nums[i] {
list = append(list, nums[i])
}
}
// cnt 维护list.index和出现次数的关系
cnt := make([]int, len(list))
for i := range nums {
index := find(list, nums[i])
if index >= 0 {
cnt[index] ++
}
}
// 遍历nums,看num + k和num - k在cnt中是否存在,更新count,完了设置cnt[i]=0
index := 0
for i := range list {
if k == 0 {
if cnt[index] > 1 {
count ++
}
} else {
a, b := find(list, list[i] + k), find(list, list[i] - k)
if a != -1 && cnt[a] > 0 {
count ++
}
if b != -1 && cnt[b] > 0 {
count ++
}
}
cnt[index] = 0
index ++
}
return count
}
// 找到num在list中的下标,如果不存在返回-1
func find(list []int, num int) int {
left, right := 0, len(list) -1
for left <= right {
mid := (left + right) >> 1
if list[mid] == num {
return mid
} else if list[mid] < num {
left = mid + 1
} else {
right = mid - 1
}
}
return -1
}