Medium
题目描述
给你一个下标从 0 开始、由正整数组成的数组 nums。
你可以在数组上执行下述操作 任意 次:
- 选择一个满足
0 <= i < nums.length - 1且nums[i] <= nums[i + 1]的下标i。将nums[i + 1]替换为nums[i] + nums[i + 1],并从数组中删除nums[i]。
返回你可以从最终数组中获得的 最大 元素的值。
示例 1:
输入:nums = [2,3,7,9,3]
输出:21
解释:我们可以在数组上执行下述操作:
- 选择 i = 0 ,得到数组 [5,7,9,3] 。
- 选择 i = 1 ,得到数组 [5,16,3] 。
- 选择 i = 0 ,得到数组 [21,3] 。
最终数组中的最大元素是 21 。可以证明我们无法获得更大的元素。
示例 2:
输入:nums = [5,3,3]
输出:11
解释:我们可以在数组上执行下述操作:
- 选择 i = 1 ,得到数组 [5,6] 。
- 选择 i = 0 ,得到数组 [11] 。
最终数组只有一个元素,即 11 。
提示:
1 <= nums.length <= 10^51 <= nums[i] <= 10^6
解题思路
这道题的核心思路是贪心 + 逆向思维。
首先理解操作规则:只有当 nums[i] <= nums[i+1] 时,才能将两个元素合并。为了获得最大的元素,我们需要尽可能地进行合并操作。
关键观察:从右向左遍历是最优策略。因为:
- 如果从左向右合并,可能会错过后续更好的合并机会
- 从右向左遍历时,我们可以贪心地尽可能合并更多元素
具体算法:
- 从数组末尾开始,维护一个当前的合并值
current - 向左遍历,对于每个元素
nums[i]:- 如果
nums[i] <= current,说明可以合并,更新current = nums[i] + current - 如果
nums[i] > current,说明无法继续合并,更新current = nums[i]
- 如果
- 遍历过程中记录遇到的最大值
这种方法保证了我们总是在最优时机进行合并,因为从右向左遍历确保了我们不会错过任何可能的合并机会。
时间复杂度为 O(n),空间复杂度为 O(1),是最优解法。
代码实现
class Solution {
public:
long long maxArrayValue(vector<int>& nums) {
long long current = nums.back();
long long maxVal = current;
for (int i = nums.size() - 2; i >= 0; i--) {
if (nums[i] <= current) {
current += nums[i];
} else {
current = nums[i];
}
maxVal = max(maxVal, current);
}
return maxVal;
}
};
class Solution:
def maxArrayValue(self, nums: List[int]) -> int:
current = nums[-1]
max_val = current
for i in range(len(nums) - 2, -1, -1):
if nums[i] <= current:
current += nums[i]
else:
current = nums[i]
max_val = max(max_val, current)
return max_val
public class Solution {
public long MaxArrayValue(int[] nums) {
long current = nums[nums.Length - 1];
long maxVal = current;
for (int i = nums.Length - 2; i >= 0; i--) {
if (nums[i] <= current) {
current += nums[i];
} else {
current = nums[i];
}
maxVal = Math.Max(maxVal, current);
}
return maxVal;
}
}
/**
* @param {number[]} nums
* @return {number}
*/
var maxArrayValue = function(nums) {
let current = nums[nums.length - 1];
let maxVal = current;
for (let i = nums.length - 2; i >= 0; i--) {
if (nums[i] <= current) {
current += nums[i];
} else {
current = nums[i];
}
maxVal = Math.max(maxVal, current);
}
return maxVal;
};
复杂度分析
| 复杂度类型 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 需要遍历数组一次,n为数组长度 |
| 空间复杂度 | O(1) | 只使用常数级额外空间 |
相关题目
. Jump Game (Medium)
. House Robber (Medium)