leetcode
leetcode 2351 ~ 2400
合并后数组中的最大元素

合并后数组中的最大元素

难度:

标签:

题目描述

You are given a 0-indexed array nums consisting of positive integers.

You can do the following operation on the array any number of times:

  • Choose an integer i such that 0 <= i < nums.length - 1 and nums[i] <= nums[i + 1]. Replace the element nums[i + 1] with nums[i] + nums[i + 1] and delete the element nums[i] from the array.

Return the value of the largest element that you can possibly obtain in the final array.

 

Example 1:

Input: nums = [2,3,7,9,3]
Output: 21
Explanation: We can apply the following operations on the array:
- Choose i = 0. The resulting array will be nums = [5,7,9,3].
- Choose i = 1. The resulting array will be nums = [5,16,3].
- Choose i = 0. The resulting array will be nums = [21,3].
The largest element in the final array is 21. It can be shown that we cannot obtain a larger element.

Example 2:

Input: nums = [5,3,3]
Output: 11
Explanation: We can do the following operations on the array:
- Choose i = 1. The resulting array will be nums = [5,6].
- Choose i = 0. The resulting array will be nums = [11].
There is only one element in the final array, which is 11.

 

Constraints:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 106

代码结果

运行时间: 60 ms, 内存: 29.8 MB


/*
 思路:
 - 与使用普通的Java实现类似,我们可以使用Java Stream API来实现该算法。
 - Stream API可以让代码更加简洁和具有函数式编程风格。
 - 由于Stream API没有内置的栈操作,我们可以使用一个列表来模拟栈的行为。
*/

import java.util.*;
import java.util.stream.*;

public class Solution {
    public int maxElement(int[] nums) {
        List<Integer> stack = new ArrayList<>();
        Arrays.stream(nums).forEach(num -> {
            while (!stack.isEmpty() && stack.get(stack.size() - 1) <= num) {
                num += stack.remove(stack.size() - 1);
            }
            stack.add(num);
        });
        return stack.stream().mapToInt(Integer::intValue).max().orElse(Integer.MIN_VALUE);
    }
}

解释

方法:

这个题解使用了一种非常特殊的方法,从数组末端开始,并尽可能地将相邻的满足条件的数合并,从而使得数组尽可能的缩减。它利用了一个重复的过程,通过不断检查并合并满足 nums[i] <= nums[i+1] 条件的相邻元素对,然后删除前者,这样不断重复,直到不能再合并为止。当数组长度减少到20以下时,程序会进一步加速处理。另外,这个解还采用了动态分段和调整段大小的策略,以尝试优化处理速度和合并效果。

时间复杂度:

O(n^2)

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中提到的`动态分段和调整段大小的策略`是如何具体实现的?能否详细解释这一策略的工作原理及其对算法性能的影响?
在题解中,动态分段和调整段大小的策略是通过改变变量`kp`的值来实现的。这个变量代表每个分段包含的元素数量。初始时`kp`设为128,根据数组的处理进度,如果`score`(当前步骤减少的数组长度与前一步骤相比)增加,说明更大的段大小可能更有效,因此将`k`(一个影响`kp`的因子)增加8倍;如果`score`减少,`k`则被设为其倒数,从而减小段大小。调整`kp`的值是通过`kp = int(kp * k) // 8`实现的。这种策略的目的是让算法能够根据当前数据的特性动态调整处理的粒度,理论上能够在不同的数据集和处理阶段优化性能,提高算法的效率和响应速度。
🦆
题解中使用了`wuhu = nums.pop`,但似乎后续并没有直接使用`wuhu()`。这种实现方式是否有特殊的目的或是存在某种误用?
在题解中,`wuhu = nums.pop`实际上是将`nums.pop`方法赋给了变量`wuhu`,这是一种简化代码的做法。然而,从代码的上下文来看,虽然`wuhu()`被调用了,但这种调用方式并未直接体现其作用,因为没有对`wuhu`的调用结果进行处理或使用。这可能是代码实现过程中的一个误用或者是为了某种未明确的副作用(例如可能原意是用来调试或检测)。如果没有具体的副作用或目的,这种做法可能会引起一些混淆或是不必要的性能开销。
🦆
在处理数组长度减少到20以下时,题解采用了不同的处理策略。为什么选择20作为阈值?这种策略在算法效率上有何具体影响?
在题解中,选择20作为处理策略改变的阈值可能基于以下考虑:当数组长度显著减小,处理每个元素的相对开销变大,因此采用更直接的方法处理小数组可能更有效。直接合并相邻满足条件的元素在小数组中操作更快,因为小规模数据上的迭代操作相对较快,且管理和维护的开销较小。此策略可以减少在小数组上不必要的复杂操作,提高算法的总体效率,尤其是在接近最终结果时。

相关问题