Medium

题目描述

给你一个长度为 n 的整数数组 nums,请你判断在最多改变一个元素的情况下,该数组是否可以变成一个非递减数列。

我们是这样定义一个非递减数列的:对于数组中任意的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]

示例 1:

输入: nums = [4,2,3]
输出: true
解释: 你可以通过把第一个 4 变成 1 来使得它成为一个非递减数列。

示例 2:

输入: nums = [4,2,1]
输出: false
解释: 你不能在只改变一个元素的情况下将其变为非递减数列。

提示:

  • n == nums.length
  • 1 <= n <= 10^4
  • -10^5 <= nums[i] <= 10^5

解题思路

这道题的关键是找到数组中的递减位置,然后判断是否可以通过修改最多一个元素来解决。

核心思路:

  1. 首先遍历数组,统计有多少个位置 i 满足 nums[i] > nums[i+1](递减位置)
  2. 如果递减位置超过1个,直接返回 false
  3. 如果没有递减位置,返回 true
  4. 如果恰好有1个递减位置,需要判断修改哪个元素能让数组变成非递减

修改策略: 当发现 nums[i] > nums[i+1] 时,有两种修改方案:

  • 方案1:将 nums[i] 修改为 nums[i+1]
  • 方案2:将 nums[i+1] 修改为 nums[i]

但要确保修改后不会与前面或后面的元素产生新的冲突:

  • 如果 i == 0nums[i-1] <= nums[i+1],可以选择方案1
  • 否则只能选择方案2

优化思路: 实际上可以一边遍历一边处理,当发现递减位置时立即修改数组,然后继续检查。如果后续还有递减位置,说明一次修改不够。

代码实现

class Solution {
public:
    bool checkPossibility(vector<int>& nums) {
        int count = 0;
        int n = nums.size();
        
        for (int i = 0; i < n - 1; i++) {
            if (nums[i] > nums[i + 1]) {
                count++;
                if (count > 1) return false;
                
                // 决定修改哪个元素
                if (i == 0 || nums[i - 1] <= nums[i + 1]) {
                    nums[i] = nums[i + 1];
                } else {
                    nums[i + 1] = nums[i];
                }
            }
        }
        
        return true;
    }
};
class Solution:
    def checkPossibility(self, nums: List[int]) -> bool:
        count = 0
        n = len(nums)
        
        for i in range(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
public class Solution {
    public bool CheckPossibility(int[] nums) {
        int count = 0;
        int n = nums.Length;
        
        for (int i = 0; i < n - 1; i++) {
            if (nums[i] > nums[i + 1]) {
                count++;
                if (count > 1) return false;
                
                // 决定修改哪个元素
                if (i == 0 || nums[i - 1] <= nums[i + 1]) {
                    nums[i] = nums[i + 1];
                } else {
                    nums[i + 1] = nums[i];
                }
            }
        }
        
        return true;
    }
}
var checkPossibility = function(nums) {
    let count = 0;
    
    for (let i = 0; i < nums.length - 1; i++) {
        if (nums[i] > nums[i + 1]) {
            count++;
            if (count > 1) return false;
            
            if (i > 0 && nums[i - 1] > nums[i + 1]) {
                nums[i + 1] = nums[i];
            } else {
                nums[i] = nums[i + 1];
            }
        }
    }
    
    return true;
};

复杂度分析

复杂度类型
时间复杂度O(n)
空间复杂度O(1)

相关题目