LeetCode 题解工作台

最大好子数组和

给你一个长度为 n 的数组 nums 和一个 正 整数 k 。 如果 nums 的一个 子数组 中,第一个元素和最后一个元素 差的绝对值恰好 为 k ,我们称这个子数组为 好 的。换句话说,如果子数组 nums[i..j] 满足 |nums[i] - nums[j]| == k ,那么它是一个好子数…

category

3

题型

code_blocks

6

代码语言

hub

3

相关题

当前训练重点

中等 · 数组·哈希·扫描

bolt

答案摘要

我们用一个哈希表 记录 的前缀数组 的和 ,如果有多个相同的 ,我们只保留最小的 。初始时,我们将 设为 。另外,我们用一个变量 记录当前的前缀和,初始时 $s = 0$。初始化答案 为 。 接下来,我们枚举 ,并且维护一个变量 表示 的和。如果 $nums[i] - k$ 在 中,那么我们就找到了一个好子数组,将答案更新为 $ans = \max(ans, s - p[nums…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 数组·哈希·扫描 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个长度为 n 的数组 nums 和一个  整数 k 。

如果 nums 的一个子数组中,第一个元素和最后一个元素 差的绝对值恰好 为 k ,我们称这个子数组为  的。换句话说,如果子数组 nums[i..j] 满足 |nums[i] - nums[j]| == k ,那么它是一个好子数组。

请你返回 nums 中  子数组的 最大 和,如果没有好子数组,返回 0 。

 

示例 1:

输入:nums = [1,2,3,4,5,6], k = 1
输出:11
解释:好子数组中第一个元素和最后一个元素的差的绝对值必须为 1 。好子数组有 [1,2] ,[2,3] ,[3,4] ,[4,5] 和 [5,6] 。最大子数组和为 11 ,对应的子数组为 [5,6] 。

示例 2:

输入:nums = [-1,3,2,4,5], k = 3
输出:11
解释:好子数组中第一个元素和最后一个元素的差的绝对值必须为 3 。好子数组有 [-1,3,2] 和 [2,4,5] 。最大子数组和为 11 ,对应的子数组为 [2,4,5] 。

示例 3:

输入:nums = [-1,-2,-3,-4], k = 2
输出:-6
解释:好子数组中第一个元素和最后一个元素的差的绝对值必须为 2 。好子数组有 [-1,-2,-3] 和 [-2,-3,-4] 。最大子数组和为 -6 ,对应的子数组为 [-1,-2,-3] 。

 

提示:

  • 2 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • 1 <= k <= 109
lightbulb

解题思路

方法一:前缀和 + 哈希表

我们用一个哈希表 pp 记录 nums[i]nums[i] 的前缀数组 nums[0..i1]nums[0..i-1] 的和 ss,如果有多个相同的 nums[i]nums[i],我们只保留最小的 ss。初始时,我们将 p[nums[0]]p[nums[0]] 设为 00。另外,我们用一个变量 ss 记录当前的前缀和,初始时 s=0s = 0。初始化答案 ansans-\infty

接下来,我们枚举 nums[i]nums[i],并且维护一个变量 ss 表示 nums[0..i]nums[0..i] 的和。如果 nums[i]knums[i] - kpp 中,那么我们就找到了一个好子数组,将答案更新为 ans=max(ans,sp[nums[i]k])ans = \max(ans, s - p[nums[i] - k])。同理,如果 nums[i]+knums[i] + kpp 中,那么我们也找到了一个好子数组,将答案更新为 ans=max(ans,sp[nums[i]+k])ans = \max(ans, s - p[nums[i] + k])。然后,如果 i+1<ni + 1 \lt n 并且 nums[i+1]nums[i + 1] 不在 pp 中,或者 p[nums[i+1]]>sp[nums[i + 1]] \gt s,我们就将 p[nums[i+1]]p[nums[i + 1]] 设为 ss

最后,如果 ans=ans = -\infty,那么我们返回 00,否则返回 ansans

时间复杂度 O(n)O(n),空间复杂度 O(n)O(n)。其中 nn 是数组的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution:
    def maximumSubarraySum(self, nums: List[int], k: int) -> int:
        ans = -inf
        p = {nums[0]: 0}
        s, n = 0, len(nums)
        for i, x in enumerate(nums):
            s += x
            if x - k in p:
                ans = max(ans, s - p[x - k])
            if x + k in p:
                ans = max(ans, s - p[x + k])
            if i + 1 < n and (nums[i + 1] not in p or p[nums[i + 1]] > s):
                p[nums[i + 1]] = s
        return 0 if ans == -inf else ans
speed

复杂度分析

指标
时间complexity is O(n) since each element is processed once and hash lookups are O(1). Space complexity is O(n) for storing prefix sums and hash map entries.
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Checks if you understand prefix sums and hash table usage for subarray problems.

  • question_mark

    Wants to see how you optimize scanning large arrays without nested loops.

  • question_mark

    Assesses whether you handle negative numbers and zero-length edge cases properly.

warning

常见陷阱

外企场景
  • error

    Recomputing subarray sums naively instead of using prefix sums causes timeouts.

  • error

    Forgetting to handle negative numbers can lead to incorrect maximum sums.

  • error

    Not checking both +k and -k differences when searching in the hash map.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Find minimum sum of good subarrays instead of maximum.

  • arrow_right_alt

    Return the number of good subarrays that meet the k difference condition.

  • arrow_right_alt

    Modify k dynamically based on subarray length or value ranges.

help

常见问题

外企场景

最大好子数组和题解:数组·哈希·扫描 | LeetCode #3026 中等