滑动窗口题目:删除子数组的最大得分

文章目录

题目

标题和出处

标题:删除子数组的最大得分

出处:1695. 删除子数组的最大得分

难度

5 级

题目描述

要求

给定一个正整数数组 nums \texttt{nums} nums,需要从中删除一个含有不同元素 的子数组。删除子数组的得分 是子数组各元素之

返回只删除一个 子数组可获得的最大得分

如果数组 b \texttt{b} b 是数组 a \texttt{a} a 的一个连续子序列,即如果它等于 al,al+1,...,ar \texttt{al,al+1,...,ar} al,al+1,...,ar,那么它就是 a \texttt{a} a 的一个子数组。

示例

示例 1:

输入: nums = 4,2,4,5,6 \texttt{nums = 4,2,4,5,6} nums = 4,2,4,5,6

输出: 17 \texttt{17} 17

解释:最优子数组是 2,4,5,6 \texttt{2,4,5,6} 2,4,5,6

示例 2:

输入: nums = 5,2,1,2,5,2,1,2,5 \texttt{nums = 5,2,1,2,5,2,1,2,5} nums = 5,2,1,2,5,2,1,2,5

输出: 8 \texttt{8} 8

解释:最优子数组是 5,2,1 \texttt{5,2,1} 5,2,11,2,5 \texttt{1,2,5} 1,2,5

数据范围

  • 1 ≤ nums.length ≤ 10 5 \texttt{1} \le \texttt{nums.length} \le \texttt{10}^\texttt{5} 1≤nums.length≤105
  • 1 ≤ numsi ≤ 10 4 \texttt{1} \le \texttt{numsi} \le \texttt{10}^\texttt{4} 1≤numsi≤104

解法

思路和算法

由于数组 nums \textit{nums} nums 中的元素都是正整数,因此对于任意子数组,在子数组的任意一端添加元素(即增加子数组的长度)后子数组中的元素和一定增加,在子数组的任意一端删除元素(即减少子数组的长度)后子数组中的元素和一定减少。为了使删除子数组的得分最大,应该使子数组尽可能长。

考虑数组 nums \textit{nums} nums 的两个不同下标 end 1 \textit{end}_1 end1 和 end 2 \textit{end}_2 end2,其中 end 1 < end 2 \textit{end}_1 < \textit{end}_2 end1<end2,分别以这两个下标作为结束下标,寻找元素各不相同的最长子数组,将这两个最长子数组的开始下标分别记为 start 1 \textit{start}_1 start1 和 start 2 \textit{start}_2 start2,则必有 start 1 ≤ start 2 \textit{start}_1 \le \textit{start}_2 start1≤start2(否则对于任意 start 2 ≤ start 3 < start 1 \textit{start}_2 \le \textit{start}_3 < \textit{start}_1 start2≤start3<start1,下标范围 start 3 , end 1 \\textit{start}_3, \\textit{end}_1 start3,end1 的子数组的元素各不相同,且长度大于下标范围 start 1 , end 1 \\textit{start}_1, \\textit{end}_1 start1,end1 的子数组)。

因此,可以使用变长滑动窗口寻找数组 nums \textit{nums} nums 中的以每个下标作为结束下标的元素各不相同的最长子数组。用 start , end \\textit{start}, \\textit{end} start,end 表示滑动窗口,初始时 start = end = 0 \textit{start} = \textit{end} = 0 start=end=0。将滑动窗口的右端点 end \textit{end} end 向右移动,移动过程中维护滑动窗口的左端点 start \textit{start} start,对于每个 end \textit{end} end 寻找元素各不相同的最大滑动窗口。

为了判断滑动窗口中是否有重复元素,需要使用哈希集合存储滑动窗口中出现的元素。用 sum \textit{sum} sum 表示滑动窗口中的元素和。对于每个右端点 end \textit{end} end,将右端点处的元素记为 num = nums end \textit{num} = \textit{nums}\\textit{end} num=numsend,执行如下操作。

  1. 将 sum \textit{sum} sum 的值增加 num \textit{num} num。

  2. 如果哈希集合中有元素 num \textit{num} num,则滑动窗口 start , end \\textit{start}, \\textit{end} start,end 中有两个元素 num \textit{num} num,因此将 sum \textit{sum} sum 的值减去 nums start \textit{nums}\\textit{start} numsstart,从哈希集合中移除元素 nums start \textit{nums}\\textit{start} numsstart,然后将 start \textit{start} start 向右移动一位,重复该操作直到哈希集合中没有元素 num \textit{num} num。

  3. 当前滑动窗口 start , end \\textit{start}, \\textit{end} start,end 中的子数组为以 end \textit{end} end 作为结束下标的元素各不相同的最长子数组,其元素和为 sum \textit{sum} sum。使用 sum \textit{sum} sum 更新最大得分。

遍历结束之后,即可得到删除子数组的最大得分。

代码

java 复制代码
class Solution {
    public int maximumUniqueSubarray(int[] nums) {
        Set<Integer> set = new HashSet<Integer>();
        int maxSum = 0;
        int sum = 0;
        int start = 0, end = 0;
        int length = nums.length;
        while (end < length) {
            int num = nums[end];
            sum += num;
            while (set.contains(num)) {
                sum -= nums[start];
                set.remove(nums[start]);
                start++;
            }
            set.add(num);
            maxSum = Math.max(maxSum, sum);
            end++;
        }
        return maxSum;
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。滑动窗口的左右端点最多各遍历数组 nums \textit{nums} nums 一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。空间复杂度主要取决于哈希集合,哈希集合中每个元素最多出现一次。

相关推荐
8Qi810 天前
LeetCode 76. 最小覆盖子串(Minimum Window Substring)
数据结构·算法·leetcode·滑动窗口·哈希表
8Qi810 天前
LeetCode 209. 长度最小的子数组(Minimum Size Subarray Sum)
java·算法·leetcode·双指针·滑动窗口
lynnlovemin13 天前
【信息学竞赛专题】滑动窗口(尺取法)超全详解|C++模板+经典例题+避坑指南
开发语言·c++·算法·滑动窗口·信息学竞赛
奶人五毛拉人一块17 天前
滑动窗口算法及习题讲解
数据结构·算法·滑动窗口·子数组
量子炒饭大师21 天前
【优化算法】滑动窗口的「义体化」重构 ——【滑动窗口】何为滑动窗口?滑动窗口算法的核心目的是什么?
c++·算法·重构·优化算法·双指针·滑动窗口
老四啊laosi24 天前
[滑动窗口] 13. 水果成篮
算法·leetcode·滑动窗口·水果成篮
handler0125 天前
滑动窗口(同向双指针)算法:模板与例题解析
c语言·c++·笔记·算法·蓝桥杯·双指针·滑动窗口
xin_nai1 个月前
LeetCode热题100(Java)(3)滑动窗口
算法·leetcode·滑动窗口
加油JIAX2 个月前
为什么边缘化先验的Hessian矩阵可分解得到Jacobian矩阵?
slam·滑动窗口·边缘化
1104.北光c°2 个月前
Leetcode3.无重复字符的最长子串 HashSet+HashMap 【hot100算法个人笔记】【java写法】
java·开发语言·笔记·程序人生·算法·leetcode·滑动窗口