701 字
4 分钟
2841. 几乎唯一子数组的最大和
2841. 几乎唯一子数组的最大和
题目描述
给你一个整数数组 nums 和两个正整数 m 和 k。
返回 nums 中长度为 k 且包含至少 m 个不同元素的子数组的最大和。如果不存在这样的子数组,返回 0。
示例 1:
输入:nums = [2,6,7,3,1,7], m = 3, k = 4输出:18解释:有 3 个长度为 4 的子数组:[2,6,7,3] 和 18,[6,7,3,1] 和 17,[7,3,1,7] 和 18。其中 [2,6,7,3] 和 [7,3,1,7] 都包含 3 个不同元素,最大和为 18。示例 2:
输入:nums = [5,9,9,2,4,5,4], m = 1, k = 3输出:23提示:
1 <= m <= k <= nums.length <= 10^51 <= nums[i] <= 10^9
解法思路
定长滑动窗口 + 哈希表维护窗口内元素的频次(本题难点在于要在 O(1) 内知道窗口里有多少个互不相同的元素)。
如何 O(1) 维护「不同元素个数」:用一个 Counter(频次哈希表)记录窗口内每个元素的出现次数。那么 len(window) 就是窗口内互不相同元素的个数。窗口滑动时:
- 右端点进窗口:
window[nums[i]] += 1; - 左端点出窗口:对应的频次减一;一旦频次减到 0 就
del window[out],这样哈希表的键数(即不同元素个数)始终准确。
沿用 入-更新-出 三步,窗口和为 cur:
- 入:右端点
nums[i]进窗口并更新频次与cur;窗口不足 k 时继续。 - 更新:窗口长度为 k 时,若
len(window) >= m(是「几乎唯一」子数组),用cur更新最大和ans。 - 出:左端点
nums[i-k+1]出窗口,频次减一(减到 0 则删除键),并从cur中扣除。
初值:第一个窗口若无 m 个不同元素,ans 保持 0(没有满足条件的子数组返回 0)。
逐步举例(nums = [2,6,7,3,1,7], m = 3, k = 4)。枚举所有长 4 窗口并检查不同元素数:
| 窗口 | 不同元素 | 是否 ≥3 | 和 |
|---|---|---|---|
| [2,6,7,3] | 4 | ✅ | 18 → ans=18 |
| [6,7,3,1] | 4 | ✅ | 17 |
| [7,3,1,7] | 3 | ✅ | 18 → ans=18 |
三种都是”几乎唯一”子数组,最大和 ans = 18,与预期一致。
思路与写法参考灵茶山艾府 2841、2461 对应题解(2461 是在本题基础上的特例:把
>= m换成== k)。
复杂度分析
- 时间复杂度:O(n),每个元素进出窗口各一次。
- 空间复杂度:O(k),哈希表大小不超过窗口长度。
代码实现
from collections import Counter
class Solution: def maxSum(self, nums: list[int], m: int, k: int) -> int: window = Counter(nums[:k]) cur = sum(nums[:k]) ans = cur if len(window) >= m else 0 for i in range(k, len(nums)): out = nums[i - k] window[out] -= 1 if window[out] == 0: del window[out] window[nums[i]] += 1 cur += nums[i] - out if len(window) >= m and cur > ans: ans = cur return ansimport unittest
class TestMaxSum(unittest.TestCase): def setUp(self): self.solution = Solution()
def test_example1(self): self.assertEqual(self.solution.maxSum([2, 6, 7, 3, 1, 7], 3, 4), 18)
def test_example2(self): self.assertEqual(self.solution.maxSum([5, 9, 9, 2, 4, 5, 4], 1, 3), 23)
def test_no_subarray(self): self.assertEqual(self.solution.maxSum([1, 1, 1], 2, 3), 0)
if __name__ == "__main__": unittest.main() 2841. 几乎唯一子数组的最大和
https://h1s97x.github.io/posts/coding/coding-2841-max-sum-almost-unique/