leetcode
leetcode 2401 ~ 2450
几乎唯一子数组的最大和

几乎唯一子数组的最大和

难度:

标签:

题目描述

You are given an integer array nums and two positive integers m and k.

Return the maximum sum out of all almost unique subarrays of length k of nums. If no such subarray exists, return 0.

A subarray of nums is almost unique if it contains at least m distinct elements.

A subarray is a contiguous non-empty sequence of elements within an array.

 

Example 1:

Input: nums = [2,6,7,3,1,7], m = 3, k = 4
Output: 18
Explanation: There are 3 almost unique subarrays of size k = 4. These subarrays are [2, 6, 7, 3], [6, 7, 3, 1], and [7, 3, 1, 7]. Among these subarrays, the one with the maximum sum is [2, 6, 7, 3] which has a sum of 18.

Example 2:

Input: nums = [5,9,9,2,4,5,4], m = 1, k = 3
Output: 23
Explanation: There are 5 almost unique subarrays of size k. These subarrays are [5, 9, 9], [9, 9, 2], [9, 2, 4], [2, 4, 5], and [4, 5, 4]. Among these subarrays, the one with the maximum sum is [5, 9, 9] which has a sum of 23.

Example 3:

Input: nums = [1,2,1,2,1,2,1], m = 3, k = 3
Output: 0
Explanation: There are no subarrays of size k = 3 that contain at least m = 3 distinct elements in the given array [1,2,1,2,1,2,1]. Therefore, no almost unique subarrays exist, and the maximum sum is 0.

 

Constraints:

  • 1 <= nums.length <= 2 * 104
  • 1 <= m <= k <= nums.length
  • 1 <= nums[i] <= 109

代码结果

运行时间: 129 ms, 内存: 19.1 MB


/*
 * 思路:
 * 使用Java Stream API来处理这个问题。
 * 我们可以利用Stream对数组进行滑动窗口操作,然后对每个窗口进行处理。
 * 使用HashSet来判断不同元素的数量并计算窗口的和。
 */
import java.util.*;
import java.util.stream.*;

public class Solution {
    public int maxSumOfAlmostUniqueSubarray(int[] nums, int m, int k) {
        return IntStream.range(0, nums.length - k + 1)
                .map(i -> {
                    Set<Integer> uniqueElements = new HashSet<>();
                    int currentSum = IntStream.range(i, i + k)
                            .peek(j -> uniqueElements.add(nums[j]))
                            .map(j -> nums[j])
                            .sum();
                    return uniqueElements.size() >= m ? currentSum : 0;
                })
                .max()
                .orElse(0);
    }
}

解释

方法:

该题解采用了滑动窗口和哈希表的方法。首先,使用哈希表`ds`来记录窗口内元素的出现次数,以及变量`s`来记录窗口内元素的和。窗口的初始位置是数组的前`k`个元素。然后,遍历数组,每次向右滑动窗口一位,更新窗口内的元素和以及哈希表的内容。如果在滑动后的窗口中,哈希表的大小(即窗口内不同元素的数量)大于等于`m`,那么就尝试更新最大和`res`。最终返回得到的最大和`res`,如果没有符合条件的子数组,则返回`0`。

时间复杂度:

O(n)

空间复杂度:

O(k)

代码细节讲解

🦆
在处理滑动窗口中的元素时,哈希表的更新策略是什么,特别是在处理元素频率为0时,为什么要从哈希表中删除该元素?
在使用滑动窗口处理数组时,哈希表用于记录窗口内每个元素的出现次数。当窗口向右移动时,窗口最左侧的元素被移除,其对应在哈希表中的计数减一。如果该元素的频率降为零,则意味着它不再出现在当前的窗口内。为了保持哈希表的准确性和减少空间占用,将频率为0的元素从哈希表中删除是必要的。这样可以确保哈希表只包含窗口内存在的元素,同时减少无用数据的存储,提高算法效率。
🦆
在更新窗口和时,为什么只考虑移除最左侧元素和添加新元素,这种操作是否足以维持窗口长度始终为k?
更新窗口和时,移除最左侧元素和添加新元素是为了保持窗口的长度恒定为k。每次滑动窗口向右移动一位,最左侧的元素被移出窗口,同时数组中的下一个元素加入窗口的右侧。这种操作确保了每次移动后窗口中的元素总数仍然是k个,从而维持了窗口的固定长度。
🦆
题解中提到如果没有符合条件的子数组则返回0,该如何判断是否存在符合条件的子数组?
在题解中,子数组是否符合条件是基于窗口内不同元素的数量是否达到或超过了m来判断。如果在整个数组遍历结束后,没有任何一个窗口的不同元素数量满足大于等于m的条件,那么意味着不存在符合条件的子数组,此时应返回0。具体实现中,可以通过设置一个初始值res=0,并只有在找到至少一个满足条件的窗口时才更新这个值,如果遍历完数组后res仍为0,则说明没有符合条件的子数组。
🦆
为什么在每次滑动窗口后只有当窗口内不同元素的数量大于等于m时,才尝试更新最大和?
题目要求寻找的是几乎唯一的子数组,其中‘几乎唯一’是通过窗口内不同元素的数量是否大于等于m来定义的。只有当窗口内不同元素的数量达到或超过m时,该窗口的元素组合才符合题目的‘几乎唯一’的要求。因此,只在这种情况下更新最大和是合适的,这样可以确保只考虑符合题目条件的子数组,避免不必要的计算和错误的结果更新。

相关问题