【数组】力扣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. 还能修改:
    修改方案1:将nums[i]缩小至nums[i + 1]
    修改方案2:将nums[i + 1]放大至nums[i]
  2. 不能修改了:直接返回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
posted @   Vonos  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示