LeetCode 题解工作台

最大化子数组的总成本

给你一个长度为 n 的整数数组 nums 。 子数组 nums[l..r] (其中 0 )的 成本 定义为: cost(l, r) = nums[l] - nums[l + 1] + ... + nums[r] * (−1) r − l 你的任务是将 nums 分割成若干子数组,使得所有子数组的成本…

category

2

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

中等 · 状态·转移·动态规划

bolt

答案摘要

根据题目描述,如果当前数没取反,那么下一个可以取反,也可以不取反;如果当前数取反了,那么下一个只能不取反。 因此,我们定义一个函数 $\textit{dfs}(i, j)$,表示从第 个数开始,第 个数是否能取反,其中 表示第 个数是否取反。如果 $j = 0$,表示第 个数不能取反,否则可以取反。答案为 $\textit{dfs}(0, 0)$。

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

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

子数组 nums[l..r](其中 0 <= l <= r < n)的 成本 定义为:

cost(l, r) = nums[l] - nums[l + 1] + ... + nums[r] * (−1)r − l

你的任务是将 nums 分割成若干子数组,使得所有子数组的成本之和 最大化,并确保每个元素 正好 属于一个子数组。

具体来说,如果 nums 被分割成 k 个子数组,且分割点为索引 i1, i2, ..., ik − 1(其中 0 <= i1 < i2 < ... < ik - 1 < n - 1),则总成本为:

cost(0, i1) + cost(i1 + 1, i2) + ... + cost(ik − 1 + 1, n − 1)

返回在最优分割方式下的子数组成本之和的最大值。

注意:如果 nums 没有被分割,即 k = 1,则总成本即为 cost(0, n - 1)

 

示例 1:

输入: nums = [1,-2,3,4]

输出: 10

解释:

一种总成本最大化的方法是将 [1, -2, 3, 4] 分割成子数组 [1, -2, 3][4]。总成本为 (1 + 2 + 3) + 4 = 10

示例 2:

输入: nums = [1,-1,1,-1]

输出: 4

解释:

一种总成本最大化的方法是将 [1, -1, 1, -1] 分割成子数组 [1, -1][1, -1]。总成本为 (1 + 1) + (1 + 1) = 4

示例 3:

输入: nums = [0]

输出: 0

解释:

无法进一步分割数组,因此答案为 0。

示例 4:

输入: nums = [1,-1]

输出: 2

解释:

选择整个数组,总成本为 1 + 1 = 2,这是可能的最大成本。

 

提示:

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

解题思路

方法一:记忆化搜索

根据题目描述,如果当前数没取反,那么下一个可以取反,也可以不取反;如果当前数取反了,那么下一个只能不取反。

因此,我们定义一个函数 dfs(i,j)\textit{dfs}(i, j),表示从第 ii 个数开始,第 ii 个数是否能取反,其中 jj 表示第 ii 个数是否取反。如果 j=0j = 0,表示第 ii 个数不能取反,否则可以取反。答案为 dfs(0,0)\textit{dfs}(0, 0)

函数 dfs(i,j)dfs(i, j) 的执行过程如下:

  • 如果 ilen(nums)i \geq \textit{len}(nums),表示已经遍历完了数组,返回 00
  • 否则,第 ii 个数可以不取反,此时答案为 nums[i]+dfs(i+1,1)nums[i] + \textit{dfs}(i + 1, 1);如果 j=1j = 1,表示第 ii 个数可以取反,此时答案为 max(dfs(i+1,0)nums[i])\max(\textit{dfs}(i + 1, 0) - nums[i])。我们取两者的最大值即可。

为了避免重复计算,我们可以使用记忆化搜索,将已经计算过的结果保存起来。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
    def maximumTotalCost(self, nums: List[int]) -> int:
        @cache
        def dfs(i: int, j: int) -> int:
            if i >= len(nums):
                return 0
            ans = nums[i] + dfs(i + 1, 1)
            if j == 1:
                ans = max(ans, -nums[i] + dfs(i + 1, 0))
            return ans

        return dfs(0, 0)
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Look for an understanding of dynamic programming and state transitions.

  • question_mark

    Evaluate the ability to optimize a solution based on greedy subarray splits.

  • question_mark

    Test the candidate's ability to calculate and maximize subarray costs effectively.

warning

常见陷阱

外企场景
  • error

    Not properly identifying valid alternating subarrays.

  • error

    Using a brute force method that doesn't take advantage of dynamic programming.

  • error

    Failing to consider all possible valid splits of the array.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Adjust the problem to handle larger arrays efficiently.

  • arrow_right_alt

    Implement a solution that handles various edge cases like single-element arrays.

  • arrow_right_alt

    Test with arrays containing both positive and negative values to explore different split patterns.

help

常见问题

外企场景

最大化子数组的总成本题解:状态·转移·动态规划 | LeetCode #3196 中等