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

目录

最大唯一元素子数组和 —— 滑动窗口解法详解

题目描述

题目示例

示例 1

示例 2

解题分析

解题方法:滑动窗口

滑动窗口核心思想

算法步骤

代码实现(Python)

复杂度分析

示例说明

示例 1

示例 2

总结


最大唯一元素子数组和 —— 滑动窗口解法详解

题目描述

给定一个正整数数组 nums,你需要从中删除一个连续子数组,该子数组的所有元素互不相同(没有重复元素)。删除这个子数组的得分定义为子数组内元素之和。

请你返回只删除一个子数组能够获得的最大得分

换句话说,就是求一个最长无重复元素的连续子数组,使得该子数组的元素和最大。


题目示例

示例 1
输入:nums = [4,2,4,5,6]
输出:17
解释:最优子数组是 [2,4,5,6],和为 2+4+5+6=17。
示例 2
输入:nums = [5,2,1,2,5,2,1,2,5]
输出:8
解释:最优子数组是 [5,2,1] 或 [1,2,5],和为 8。

解题分析

题目要求的是找到一个连续子数组,这个子数组没有重复元素,并且它的元素和最大。

这是一个典型的“最长无重复子串/子数组”问题的变种:

  • 我们需要的不是最长无重复子数组的长度,而是最大和。
  • 子数组必须是连续的。

根据这些要求,**滑动窗口(双指针)**是解决此类问题的经典方法。


解题方法:滑动窗口

滑动窗口核心思想

  • 维护两个指针 leftright,表示当前考察的子数组边界。
  • 用一个集合(seen)存储当前窗口内的元素,保证窗口内元素唯一。
  • 使用一个变量 window_sum 维护当前窗口内元素的和。
  • 使用一个变量 max_sum 来维护迄今为止遇到的最大和。

算法步骤

  1. 初始化:left = 0, right = 0,空集合 seenwindow_sum = 0max_sum = 0
  2. 右指针 right 从左向右遍历数组元素:
    • 如果当前元素 nums[right] 不在集合 seen 中,直接将其加入 seenwindow_sum 加上这个元素。
    • 如果当前元素在 seen 中,说明有重复元素出现,开始移动左指针 left
      • 不断移除 nums[left],从 seen 中删除对应元素,同时从 window_sum 减去它的值。
      • 直到 nums[right] 不再在 seen 中为止。
  1. 每次右指针右移后,更新 max_sum = max(max_sum, window_sum)
  2. 遍历结束后,max_sum 就是最大无重复元素子数组的和。

代码实现(Python)

from typing import List

class Solution:
    def maximumUniqueSubarray(self, nums: List[int]) -> int:
        seen = set()
        left = 0
        window_sum = 0
        max_sum = 0

        for right in range(len(nums)):
            # 如果遇到重复元素,左指针右移直到移除重复元素
            while nums[right] in seen:
                seen.remove(nums[left])
                window_sum -= nums[left]
                left += 1
            # 添加当前元素
            seen.add(nums[right])
            window_sum += nums[right]
            # 更新最大和
            max_sum = max(max_sum, window_sum)

        return max_sum

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组长度。每个元素最多被左右指针访问两次(一次加入窗口,一次移出窗口)。
  • 空间复杂度:O(k),k 是窗口最大长度,即无重复元素的最长子数组长度,用于存储集合中的元素。

示例说明

示例 1

nums = [4,2,4,5,6]

  • 初始化:left=0, right=0, seen={}, window_sum=0, max_sum=0
  • right=0: 4不重复,加入,窗口和=4,max_sum=4
  • right=1: 2不重复,加入,窗口和=6,max_sum=6
  • right=2: 4重复,左指针移动,移除第一个4,窗口和=2,left=1;再次检查,4不重复,加入窗口和=6,max_sum=6
  • right=3: 5不重复,加入,窗口和=11,max_sum=11
  • right=4: 6不重复,加入,窗口和=17,max_sum=17
  • 结束,最大和为17,对应子数组 [2,4,5,6]

示例 2

nums = [5,2,1,2,5,2,1,2,5]

  • 右指针移动加入元素,遇到重复时左指针右移移除元素
  • 最大无重复子数组为 [5,2,1][1,2,5],和为 8

总结

  • 该题是典型的滑动窗口应用,适合用双指针动态维护无重复子数组。
  • 关键在于使用一个集合快速判断重复,和维护当前窗口元素和。
  • 该算法时间效率高,能应对较大规模输入。
  • 思路也适用于“最长无重复子串”这类类似问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值