题目:
给你一个整数数组 nums 和一个整数 k ,请你返回 nums 中 好 子数组的数目。
一个子数组 arr 如果有 至少 k 对下标 (i, j) 满足 i < j 且 arr[i] == arr[j] ,那么称它是一个 好 子数组。
子数组 是原数组中一段连续 非空 的元素序列。
算法
方法一:双指针(固定右边界)(不定长滑动窗口)
思路:问题考察存在多少个连续子数组,存在good pair count 大于等于k。连续子数组是一个不定长的窗口,问题可以转化为存在多少个窗口,窗口内的good pair count 大于等于k。
1.如何统计窗口内的good pair数?
用一个map count记录窗口内每个数字出现的次数,用pair记录窗口内的good pair数。窗口的右边界right右移时,good pair cound增加count[right],count[right]++。窗口的左边界left右移时,good pair cound减少count[left],count[right]--。
这样我们就能实时维护窗口内的good pair count
2.那么窗口怎么移动呢?
我们固定右边界right,left右移直到窗口[left + 1,right]不存在满足条件的子数组:
0--->left-------right
此时,符合条件的子数组长度为left + 1,然后我们将right右移。
注意,left不能移动到不满足的left + 1去,因为随着nums[right]可能和nums[right + 1]相等,随着right的右移,left + 1可能变成符合条件的左端点
3.窗口右移(left->left2, right->right2)之后,新增满足条件的子数组数量是多少?
0--->left---(left2)----right---(right2)
1.左边界为[0,left],右边界为为right2的数字均满足条件(因为right时good pair对就满足条件,再增加一下长度同样满足)。
2.左边界为[left+1. left2],右边界为为right2,同样满足(不满足left就不会右移)
所以以right2为右端点的good pair对长度大于等于k的子数组数目就是left2 + 1
套路:
子数组统计问题通常用不定长滑动窗口(双指针解决)
func countGood(nums []int, k int) int64 {
// 窗口内各个数的数量
numCount := make(map[int]int)
ans := int64(0)
// 窗口内good pair count
windowPairs := 0
for left, right := 0, 0; right < len(nums); right ++ {
windowPairs = windowPairs + numCount[nums[right]]
numCount[nums[right]] ++
for left < len(nums) && windowPairs - numCount[nums[left]] + 1 >= k {
// left右移,good pair count减少numCount[nums[left]] - 1
windowPairs = windowPairs - numCount[nums[left]] + 1
numCount[nums[left]] --
left ++
}
if windowPairs >= k {
ans = ans + int64(left + 1)
}
}
return ans
}
方法二:双指针 (固定左边界)
子数组nums[i,j]至少有k对good pair,则nums[i,j+1]...nums[i,n]
func countGood(nums []int, k int) int64 {
numCount := make(map[int]int)
ans := int64(0)
windowPairs := 0
for left, right := 0, 0; right < len(nums); right ++ {
windowPairs = windowPairs + numCount[nums[right]]
numCount[nums[right]] ++
// left为满足条件的子字符串的左端点,左端点每变一次,ans增加一次
for windowPairs >= k {
ans = ans + int64(len(nums) - right)
windowPairs = windowPairs - numCount[nums[left]] + 1
numCount[nums[left]] --
left ++
}
}
return ans
}