【每日一题】LeetCode 2841.几乎唯一子数组的最大和(数组、哈希、滑动窗口)

发布于:2024-09-18 ⋅ 阅读:(11) ⋅ 点赞:(0)

【每日一题】LeetCode 2841.几乎唯一子数组的最大和(数组、哈希、滑动窗口)

题目描述

给定一个整数数组 nums 和两个正整数 mk,任务是找出 nums 中长度为 k几乎唯一 子数组的最大和。如果不存在这样的子数组,则返回 0

几乎唯一子数组 定义为:子数组中至少有 m 个互不相同的元素。

子数组是指数组中一段连续非空的元素序列。

  • nums:一个整数数组。
  • m:一个正整数,表示至少有多少个互不相同的元素。
  • k:一个正整数,表示子数组的长度。

示例

示例 1

  • 输入:nums = [2,6,7,3,1,7], m = 3, k = 4
  • 输出:18
  • 解释:有三个长度为 4 的几乎唯一子数组 [2, 6, 7, 3][6, 7, 3, 1][7, 3, 1, 7]。其中和最大的是 [2, 6, 7, 3],和为 18

示例 2

  • 输入:nums = [5,9,9,2,4,5,4], m = 1, k = 3
  • 输出:23
  • 解释:有五个长度为 3 的几乎唯一子数组 [5, 9, 9][9, 9, 2][9, 2, 4][2, 4, 5][4, 5, 4]。其中和最大的是 [5, 9, 9],和为 23

示例 3

  • 输入:nums = [1,2,1,2,1,2,1], m = 3, k = 3
  • 输出:0
  • 解释:不存在长度为 3 的子数组含有至少 3 个互不相同元素的子数组,因此不存在几乎唯一子数组,最大和为 0

思路分析

要解决这个问题,我们可以使用滑动窗口的方法。首先,我们初始化一个窗口,使其包含数组的前 k 个元素。然后,我们检查这个窗口是否满足至少有 m 个互不相同的元素的条件。如果满足,我们就记录下这个窗口的和。接着,我们开始滑动窗口,每次向右移动一个元素,移除窗口最左边的元素,并添加一个新的元素到窗口的右边。在每次移动后,我们都需要更新窗口内元素的计数,并检查是否仍然满足条件。如果满足,我们就更新最大和。这个过程一直持续到窗口滑动到数组的末尾。

代码实现

import java.util.HashMap;
import java.util.List;
import java.util.Map;

class Solution {
    public long maxSum(List<Integer> nums, int m, int k) {
        // 使用 HashMap 来存储窗口内元素的频率
        Map<Integer, Integer> hashMap = new HashMap<>();
        // 初始化最大和为 0
        long max = 0;
        // 初始化当前窗口的和
        long count = 0;

        // 填充第一个窗口
        for (int i = 0; i < k; i++) {
            int num = nums.get(i);
            hashMap.put(num, hashMap.getOrDefault(num, 0) + 1);
            count += num;
        }
        // 检查第一个窗口是否满足条件
        if (hashMap.size() >= m) {
            max = count;
        }

        // 开始滑动窗口
        for (int i = k; i < nums.size(); i++) {
            // 移除窗口最左边的元素
            int oldnum = nums.get(i - k);
            count -= oldnum;
            hashMap.put(oldnum, hashMap.get(oldnum) - 1);
            // 如果某个元素的计数变为 0,则从 HashMap 中移除
            if (hashMap.get(oldnum) == 0) {
                hashMap.remove(oldnum);
            }
            // 添加新元素到窗口
            int newnum = nums.get(i);
            hashMap.put(newnum, hashMap.getOrDefault(newnum, 0) + 1);
            count += newnum;
            // 检查当前窗口是否满足条件,并更新最大和
            if (hashMap.size() >= m) {
                max = Math.max(max, count);
            }
        }
        return max;
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到