LeetCode 665. 非递减数列
题目描述

题意分析
判断能否最多修改一个元素,使每对相邻元素都满足前者不大于后者。相等是合法的,原数组已经非递减时可以不修改。下面通过实际调整数组验证是否可行,因此函数会修改输入。
解法:一次修改贪心
核心思路
[!blue]
从左向右检查,保持已经处理的前缀非递减。若
nums[i - 1] <= nums[i],当前顺序正确;否则这两个相邻位置至少要改一个,修改其他位置无法消除它们之间的下降。优先把前一个值降为当前值,即
nums[i - 1] = nums[i]。这样当前值保持较小,后面的元素更容易接上。但下降后的前一个值还必须不小于nums[i - 2],所以只有i < 2,或nums[i] >= nums[i - 2]时才能这样改。如果
nums[i] < nums[i - 2],要降低前一个值,就会同时要求它不小于nums[i - 2]且不大于nums[i],两个条件无法兼得。此时只能提高当前值,设为nums[i - 1],这是维持前缀有序所需的最小值,也给后续留下最多余地。因此,每次修复都在保证前缀有序的前提下,让接下来要承接的值尽量小。若在修复后的数组上又出现下降,就需要第二次修改,而第一次采用的其他合法改法不会更有利,故可以返回
false。扫描结束且没有超过一次修改,就找到了可行方案。
解题步骤
- 初始化修改次数
count = 0,从下标 1 开始检查相邻元素。- 若当前值不小于前值,直接继续。
- 出现下降时将
count加一;若超过 1,立即返回false。- 若没有再前一个元素,或当前值不小于它,降低前值;否则提高当前值。
- 后续比较使用实际修改后的数组。遍历完成返回
true。
代码实现
// 若 i < 2 或 nums[i] >= nums[i-2],则下调 nums[i-1]。
class Solution {
public boolean checkPossibility(int[] nums) {
int count = 0;
for (int i = 1; i < nums.length; i++) {
if (nums[i] < nums[i - 1]) {
count++;
if (count > 1) {
return false;
}
// 优先降低前值,但不能破坏它与更早节点的顺序
if (i < 2 || nums[i] >= nums[i - 2]) {
nums[i - 1] = nums[i];
} else {
// 降低前值不可行,只能提高当前值并继续检查后续
nums[i] = nums[i - 1];
}
}
}
return true;
}
}
// 若 i < 2 或 nums[i] >= nums[i-2],则下调 nums[i-1]。
func checkPossibility(nums []int) bool {
count := 0
for i := 1; i < len(nums); i++ {
if nums[i] < nums[i-1] {
count++
if count > 1 {
return false
}
// 优先降低前值,但不能破坏它与更早节点的顺序
if i < 2 || nums[i] >= nums[i-2] {
nums[i-1] = nums[i]
} else {
// 降低前值不可行,只能提高当前值并继续检查后续
nums[i] = nums[i-1]
}
}
}
return true
}
复杂度分析
- 时间复杂度:$O(n)$,单向扫描。
- 空间复杂度:$O(1)$,修改写入输入数组。
关键点总结
[!green]
- 第一次下降只能通过修改这对相邻元素之一来修复。
- 能降低前值时优先降低;不能降低时,提高当前值到刚好满足前缀顺序即可。
- 后续检查必须基于修复后的值,原数组的下降次数本身不足以决定答案。
易错点总结
[!yellow]
- 降低前值前不检查
nums[i - 2],会在已经扫描过的前方制造新下降。- 一律提高当前值,会让后续需要承接的值不必要地变大,可能错过可行方案。
- 非递减允许相等,下降判断用
<,允许降低的边界判断用>=。- 本实现不撤销修改,即使最终返回
false,输入也可能已经被改过。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 896. 单调数列 | 简单 | 原题只判断单调性,本题允许修改一个值,需要在首次下降处决定改前项还是后项。 |
| 1909. 删除一个元素使数组严格递增 | 简单 | 原题删除一项后要求严格递增,本题修改一项后只要求非递减,局部边界判定不同。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!