给你一个下标从 0 开始的整数数组 nums
。
你可以执行任意次操作。每次操作中,你需要选择一个 子数组 ,并将这个子数组用它所包含元素的 和 替换。比方说,给定数组是 [1,3,5,6]
,你可以选择子数组 [3,5]
,用子数组的和 8
替换掉子数组,然后数组会变为 [1,8,6]
。
请你返回执行任意次操作以后,可以得到的 最长非递减 数组的长度。
子数组 指的是一个数组中一段连续 非空 的元素序列。
示例 1:
```txt
输入:nums = [5,2,2]
输出:1
解释:这个长度为 3 的数组不是非递减的。
我们有 2 种方案使数组长度为 2 。
第一种,选择子数组 [2,2] ,对数组执行操作后得到 [5,4] 。
第二种,选择子数组 [5,2] ,对数组执行操作后得到 [7,2] 。
这两种方案中,数组最后都不是 非递减 的,所以不是可行的答案。
如果我们选择子数组 [5,2,2] ,并将它替换为 [9] ,数组变成非递减的。
所以答案为 1 。
```
示例 2:
```txt
输入:nums = [1,2,3,4]
输出:4
解释:数组已经是非递减的。所以答案为 4 。
```
示例 3:
```txt
输入:nums = [4,3,2,6]
输出:3
解释:将 [3,2] 替换为 [5] ,得到数组 [4,5,6] ,它是非递减的。
最大可能的答案为 3 。
```
提示:
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5
找到最大非递减数组的长度
题目
给你一个下标从 0 开始的整数数组 nums
。
你可以执行任意次操作。每次操作中,你需要选择一个 子数组 ,并将这个子数组用它所包含元素的 和 替换。比方说,给定数组是 [1,3,5,6]
,你可以选择子数组 [3,5]
,用子数组的和 8
替换掉子数组,然后数组会变为 [1,8,6]
。
请你返回执行任意次操作以后,可以得到的 最长非递减 数组的长度。
子数组 指的是一个数组中一段连续 非空 的元素序列。
示例 1:
1 | 输入:nums = [5,2,2] |
示例 2:
1 | 输入:nums = [1,2,3,4] |
示例 3:
1 | 输入:nums = [4,3,2,6] |
提示:
-
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5
题解
方法一:
思路
动态规划,对于每个前缀nums[0...i]
,让$f_{i}$表示为该前缀的变为最长非递减数组的长度。$e_{i}$表示为最长非递减数组的最后一个数最小的情况。
也就是说我们不仅要让一个数组变为最长非递减数组,而且还要让这个数组的末尾元素最小化。
设$ps$为前i个数的前缀和。
状态转移$f_i = 1 + \max \limits_{j < i, ps_i-ps_j\ge e_j} f_j$,$f$是非递减的。
为了保证$e_i$尽量小,我们选择比较大的$j$进行转移
对于$j’ < j’’$,均满足$ps_{j’}+e_{j’}\le ps_i$,$ps_{j’’}+e_{j’’}\le ps_i$
当$ps_{j’}+e_{j’} \ge ps_{j’’}+e_{j’’}$,由于$ps_{j’} < ps_{j’’}$,所以$e_{j’}>e_{j’’}$,我们优先选择$j’’$作为转移位置。我们可以维护一个严格增长的单调队列,队列内元素$i,j,(i<j)$满足$ps_{i}+e_{i} < ps_{j}+e_{j}$
在求$f_i$前,如果移除队首元素后,新的队首元素x,仍然满足$ps_{x}+e_{x} \le ps_{i}$,那么不断移除队首知道违背此条件。这样做为了让队首元素尽量大,这样得到$e_i$会尽量小。
在求得$f_i$后,弹出队尾元素维护队列单调。
代码
1 | class Solution { |