From b475dbf3ed59c94ebf85b1eea821b17f35307e07 Mon Sep 17 00:00:00 2001 From: gameloader Date: Sat, 30 Mar 2024 11:27:20 +0800 Subject: [PATCH] leetcode update --- content/posts/leetcode.md | 90 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 00d760b..9276122 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -2342,3 +2342,93 @@ func countSubarrays(nums []int, k int) int64 { return count } ``` + +## day32 2024-03-30 + +### 992. Subarrays with K Different Integers + +Given an integer array nums and an integer k, return the number of good subarrays of nums. + +A good array is an array where the number of different integers in that array is exactly k. + +For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3. +A subarray is a contiguous part of an array. +![0330GvIAMJljJeoJ](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0330GvIAMJljJeoJ.png) + +### 题解 + +本题仍然使用滑动窗口, 这几天连续做滑动窗口的题, 总结了滑动窗口的"三要素": 1. 什么时候扩大窗口 2. 双么时候缩小窗口 3. 缩小和扩大窗口时执行哪些操作 +对于本题, 题目中要求计数正好包含k个不同数的子数组的个数, 求精确包含k个这种问题往往比较困难, 可以转化为求解包含≤k个和≤k-1个不同数的子数组个数的差. 这种思路求解起来非常方便. 对于求解包含≤k个不同数的子数组的个数, 当数组中包含不同数个数不足k时, 扩大窗口同时将计数增加当前窗口的长度, 若为k+1, 则缩小窗口至正好完全去除了一个数(若某个数只出现了1次, 去掉后窗口内不同数个数就是k, 若不止一次, 则去掉了不同数个数也没有变化, 故要继续向下遍历). 最后求≤k和≤k-1情况的计数值做差即可. + +### 代码 + +```go +func subarraysWithKDistinct(nums []int, k int) int { + + return countk(nums, k) - countk(nums, k-1) +} + +func countk(nums []int, k int) int { + count := map[int]int{} + different := 0 + left := 0 + result := 0 + for index, value := range nums { + _, exist := count[value] + if !exist { + different++ + count[value] = 1 + } else { + count[value]++ + } + if different <= k { + result += index - left + 1 + } + if different == k+1 { + for count[nums[left]] > 1 { + count[nums[left]]-- + left++ + } + delete(count, nums[left]) + left++ + different-- + result += index - left + 1 + } + } + return result +} +``` + +### 总结 + +解题时没有注意题目限制, 后来查看最快解法发现忽略了题目中的数的范围, 题目中的数组中的数的大小不超过数组的长度, 数的范围已知, 因此可以使用数组代替哈希表来计数这样可以大大加快解题速度. + +```go +func subarraysWithKDistinct(nums []int, k int) (ans int) { + f := func(k int) []int { + n := len(nums) + pos := make([]int, n) + cnt := make([]int, n+1) + s, j := 0, 0 + for i, x := range nums { + cnt[x]++ + if cnt[x] == 1 { + s++ + } + for ; s > k; j++ { + cnt[nums[j]]-- + if cnt[nums[j]] == 0 { + s-- + } + } + pos[i] = j + } + return pos + } + left, right := f(k), f(k-1) + for i := range left { + ans += right[i] - left[i] + } + return +} +```