【数组】力扣665:非递减数列
给你一个长度为 n 的整数数组 nums ,请你判断在最多改变 1 个元素的情况下,该数组能否变成一个非递减数列。
我们是这样定义一个非递减数列的: 对于数组中任意的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。
示例1:
输入: nums = [4,2,3]
输出: true
解释: 你可以通过把第一个 4 变成 1 来使得它成为一个非递减数列。
本题是要维持一个非递减的数列,所以遇到递减的情况时(nums[i] > nums[i + 1]),要么将前面的元素缩小,要么将后面的元素放大。
但是本题唯一的易错点就在这:
- 如果将nums[i]缩小,可能会导致其无法融入前面已经遍历过的非递减子数列
- 如果将nums[i + 1]放大,可能会导致其后续的继续出现递减
所以要采取贪心的策略,在遍历时,每次需要看连续的三个元素,也就是瞻前顾后,遵循以下两个原则:
- 尽可能不放大nums[i + 1],这样会让后续非递减更困难
- 如果缩小nums[i],但不破坏前面的子序列的非递减性
算法步骤
遍历数组,如果遇到递减:
- 还能修改:
修改方案1:将nums[i]缩小至nums[i + 1]
修改方案2:将nums[i + 1]放大至nums[i] - 不能修改了:直接返回false。
作者:Terry2020
链接:https://leetcode-cn.com/problems/non-decreasing-array/solution/yi-ding-yao-rang-ni-nong-dong-wei-shi-ya-u9te/
class Solution:
def checkPossibility(self, nums: List[int]) -> bool:
n = len(nums)
count = 0
for i in range(0, n-1):
if nums[i] > nums[i + 1]:
count += 1
if count > 1:
return False # 不需遍历完,提前结束
if i == 0 or nums[i + 1] >= nums[i - 1]:
nums[i] = nums[i + 1]
else:
nums[i + 1] = nums[i]
return True # 也可以返回 count <= 1
相当于寻找最小上升序列,只需要遍历,使得相邻3个元素有序且尽可能小,也就是考虑3个元素就行了, 分2种情况,如: [3,4,2]应为[3,4,4]; [1,4,2]应为[1,2,2]; #第2种情况,只需要记录逆序个数,中间的数字不用再赋值了,不影响后面的计数。
优化版本:只试探一种情况
class Solution:
def checkPossibility(self, nums: List[int]) -> bool:
n = len(nums)
count = 0
for i in range(0, n-1):
if nums[i] > nums[i + 1]:
count += 1
if count > 1:
return False
if i > 0 and nums[i + 1] < nums[i - 1]:
nums[i + 1] = nums[i]
return True
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理