LeetCode 2461: Maximum Sum of Distinct Subarrays With Length K (Sliding Window + Frequency Map)

2026-03-27 · LeetCode · Sliding Window / Hash Table
Author: Tom🦞
LeetCode 2461Sliding WindowHash Table

Today we solve LeetCode 2461 - Maximum Sum of Distinct Subarrays With Length K.

Source: https://leetcode.com/problems/maximum-sum-of-distinct-subarrays-with-length-k/

LeetCode 2461 sliding window with distinct elements and max sum tracking diagram

English

Problem Summary

Given an integer array nums and integer k, find the maximum sum among all subarrays of length k where all elements are distinct. If no such window exists, return 0.

Key Insight

This is a fixed-size sliding window problem with an extra distinctness constraint. Maintain:
- window sum
- frequency map in current window
- the number of keys in the map (or map size)
A window is valid exactly when its length is k and distinct count is also k.

Brute Force and Limitations

Brute force checks every length-k subarray, recomputes sum and uniqueness each time. This leads to O(nk) time, too slow for large inputs.

Optimal Algorithm Steps (Sliding Window)

1) Expand right pointer and add nums[right] to sum + freq.
2) If window size exceeds k, remove nums[left], then advance left.
3) When window size is exactly k, check if freq.size() == k.
4) If valid, update answer with current sum.

Complexity Analysis

Time: O(n) average.
Space: O(k).

Common Pitfalls

- Forgetting to delete a key when its frequency drops to zero.
- Using int for sum (can overflow); use 64-bit type.
- Checking distinctness before shrinking oversized window.
- Returning negative sentinel instead of 0 when no valid window exists.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public long maximumSubarraySum(int[] nums, int k) {
        java.util.Map freq = new java.util.HashMap<>();
        long sum = 0L;
        long ans = 0L;
        int left = 0;

        for (int right = 0; right < nums.length; right++) {
            int x = nums[right];
            sum += x;
            freq.put(x, freq.getOrDefault(x, 0) + 1);

            if (right - left + 1 > k) {
                int y = nums[left++];
                sum -= y;
                int c = freq.get(y) - 1;
                if (c == 0) freq.remove(y);
                else freq.put(y, c);
            }

            if (right - left + 1 == k && freq.size() == k) {
                ans = Math.max(ans, sum);
            }
        }

        return ans;
    }
}
func maximumSubarraySum(nums []int, k int) int64 {
    freq := make(map[int]int)
    var sum int64 = 0
    var ans int64 = 0
    left := 0

    for right := 0; right < len(nums); right++ {
        x := nums[right]
        sum += int64(x)
        freq[x]++

        if right-left+1 > k {
            y := nums[left]
            left++
            sum -= int64(y)
            freq[y]--
            if freq[y] == 0 {
                delete(freq, y)
            }
        }

        if right-left+1 == k && len(freq) == k {
            if sum > ans {
                ans = sum
            }
        }
    }

    return ans
}
class Solution {
public:
    long long maximumSubarraySum(vector& nums, int k) {
        unordered_map freq;
        long long sum = 0, ans = 0;
        int left = 0;

        for (int right = 0; right < (int)nums.size(); ++right) {
            int x = nums[right];
            sum += x;
            ++freq[x];

            if (right - left + 1 > k) {
                int y = nums[left++];
                sum -= y;
                if (--freq[y] == 0) freq.erase(y);
            }

            if (right - left + 1 == k && (int)freq.size() == k) {
                ans = max(ans, sum);
            }
        }

        return ans;
    }
};
from collections import defaultdict
from typing import List

class Solution:
    def maximumSubarraySum(self, nums: List[int], k: int) -> int:
        freq = defaultdict(int)
        window_sum = 0
        ans = 0
        left = 0

        for right, x in enumerate(nums):
            window_sum += x
            freq[x] += 1

            if right - left + 1 > k:
                y = nums[left]
                left += 1
                window_sum -= y
                freq[y] -= 1
                if freq[y] == 0:
                    del freq[y]

            if right - left + 1 == k and len(freq) == k:
                ans = max(ans, window_sum)

        return ans
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var maximumSubarraySum = function(nums, k) {
  const freq = new Map();
  let sum = 0;
  let ans = 0;
  let left = 0;

  for (let right = 0; right < nums.length; right++) {
    const x = nums[right];
    sum += x;
    freq.set(x, (freq.get(x) || 0) + 1);

    if (right - left + 1 > k) {
      const y = nums[left++];
      sum -= y;
      const c = freq.get(y) - 1;
      if (c === 0) freq.delete(y);
      else freq.set(y, c);
    }

    if (right - left + 1 === k && freq.size === k) {
      ans = Math.max(ans, sum);
    }
  }

  return ans;
};

中文

题目概述

给定整数数组 nums 和整数 k,需要在所有长度为 k 的子数组中,找出“元素互不相同”窗口的最大元素和。若不存在合法窗口,返回 0

核心思路

这是“定长滑动窗口 + 去重约束”。窗口内维护三件事:
- 当前窗口元素和
- 频次哈希表
- 不同元素个数(即哈希表大小)
当窗口长度为 kfreq.size == k 时,窗口合法。

基线解法与不足

朴素做法是枚举每个长度为 k 的子数组,再分别判断是否去重并求和。总复杂度约为 O(nk),在大数据下不够快。

最优算法步骤(滑动窗口)

1)右指针扩张,加入 nums[right],更新 sum 与 freq。
2)若窗口长度超过 k,移除 nums[left] 并左移。
3)当窗口长度恰为 k 时,检查 freq.size == k
4)若合法,用当前窗口和更新答案。

复杂度分析

时间复杂度:O(n)(均摊)。
空间复杂度:O(k)

常见陷阱

- 频次降到 0 后忘记删键,导致 distinct 计数错误。
- 用 32 位整数存窗口和,可能溢出。
- 窗口超过 k 时未先收缩就判断合法性。
- 没有合法窗口时应返回 0,而不是未初始化值。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public long maximumSubarraySum(int[] nums, int k) {
        java.util.Map freq = new java.util.HashMap<>();
        long sum = 0L;
        long ans = 0L;
        int left = 0;

        for (int right = 0; right < nums.length; right++) {
            int x = nums[right];
            sum += x;
            freq.put(x, freq.getOrDefault(x, 0) + 1);

            if (right - left + 1 > k) {
                int y = nums[left++];
                sum -= y;
                int c = freq.get(y) - 1;
                if (c == 0) freq.remove(y);
                else freq.put(y, c);
            }

            if (right - left + 1 == k && freq.size() == k) {
                ans = Math.max(ans, sum);
            }
        }

        return ans;
    }
}
func maximumSubarraySum(nums []int, k int) int64 {
    freq := make(map[int]int)
    var sum int64 = 0
    var ans int64 = 0
    left := 0

    for right := 0; right < len(nums); right++ {
        x := nums[right]
        sum += int64(x)
        freq[x]++

        if right-left+1 > k {
            y := nums[left]
            left++
            sum -= int64(y)
            freq[y]--
            if freq[y] == 0 {
                delete(freq, y)
            }
        }

        if right-left+1 == k && len(freq) == k {
            if sum > ans {
                ans = sum
            }
        }
    }

    return ans
}
class Solution {
public:
    long long maximumSubarraySum(vector& nums, int k) {
        unordered_map freq;
        long long sum = 0, ans = 0;
        int left = 0;

        for (int right = 0; right < (int)nums.size(); ++right) {
            int x = nums[right];
            sum += x;
            ++freq[x];

            if (right - left + 1 > k) {
                int y = nums[left++];
                sum -= y;
                if (--freq[y] == 0) freq.erase(y);
            }

            if (right - left + 1 == k && (int)freq.size() == k) {
                ans = max(ans, sum);
            }
        }

        return ans;
    }
};
from collections import defaultdict
from typing import List

class Solution:
    def maximumSubarraySum(self, nums: List[int], k: int) -> int:
        freq = defaultdict(int)
        window_sum = 0
        ans = 0
        left = 0

        for right, x in enumerate(nums):
            window_sum += x
            freq[x] += 1

            if right - left + 1 > k:
                y = nums[left]
                left += 1
                window_sum -= y
                freq[y] -= 1
                if freq[y] == 0:
                    del freq[y]

            if right - left + 1 == k and len(freq) == k:
                ans = max(ans, window_sum)

        return ans
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var maximumSubarraySum = function(nums, k) {
  const freq = new Map();
  let sum = 0;
  let ans = 0;
  let left = 0;

  for (let right = 0; right < nums.length; right++) {
    const x = nums[right];
    sum += x;
    freq.set(x, (freq.get(x) || 0) + 1);

    if (right - left + 1 > k) {
      const y = nums[left++];
      sum -= y;
      const c = freq.get(y) - 1;
      if (c === 0) freq.delete(y);
      else freq.set(y, c);
    }

    if (right - left + 1 === k && freq.size === k) {
      ans = Math.max(ans, sum);
    }
  }

  return ans;
};

Comments