665. 非递减数列

文章讨论了一个编程问题,即给定一个整数数组,需要判断在最多更改一个元素的情况下,是否能使其变为非递减数列。文中提出了两种思路,一种是遍历数组检查需要调整的位置,并考虑两种调整方法;另一种是统计“下降”次数,根据下降次数来决定是否可能达成目标。最后给出了相应的Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给你一个长度为 n 的整数数组 nums ,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。
我们是这样定义一个非递减数列的: 对于数组中任意的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。
示例 1:
输入: nums = [4,2,3]
输出: true
解释: 你可以通过把第一个 4 变成 1 来使得它成为一个非递减数列。
示例 2:
输入: nums = [4,2,1]
输出: false
解释: 你不能在只改变一个元素的情况下将其变为非递减数列。

思路一:

对数组进行遍历,如果遇到nums[i] > nums[i+1]那么就是必须要进行调整的。
调整无非就是有二个方法:

  • 方法一:把nums[i]改小变成nums[i+1],但是又不能小于nums[i-1];所以
    要求nums[i+1]必须大于或者等于nums[i-1],如果nums[i+1]<nums[i-1]那么就是肯定怎么改都不和题意了,直接返回False
  • 方法二:把nums[i+1]改大变成nums[i],但是又不能大于nums[i+2]。所以
    要求nums[i]必须小于或者等于nums[i+2],如果nums[i]大于nums[i+2]那么就是肯定怎么改都不和题意了,直接返回False
  • 边界情况:当i==0,也就是处理数组第一个和第二个元素的时候,那么肯定是怎么改都不会小于nums[i-1]的了,所以直接nums[i]改小为nums[i+1]
  • 当处理数组倒数第二个和倒数第一个元素的时候,也是怎么改大都不会大于i+2了,所以直接nums[i+1]改大为nums[i]

举例说明:
比如 2,8,5,6 这种,我们就只能选择方法一把8改小变成5,因为如果选择方法二,就变成2,8,8,6,就不对了,应该是2,5,5,6才对
比如 2,8,1,9 这种,我们就只能选择方法二把1改成8,因为如果选择方法一,就变成2,1,1,9就不对了,应该是2,8,8,9才对
其他的情况,比如 2,8,1,6 这种,或者 2,8,6,7就是False,怎么改都不行了

思路二:
如果存在i,使的nums[i+1]<nums[i],我们就说出现了一次“下降”

分3种情况:
1、不存在下降的情况,即下降次数为0,返回true。
2、只出现了1次下降,将下降后的元素记为nums[x](1=<x<n)
此时,可以将nums[x-1]变小,或将nums[x]变大,以达到“非递减”的目的。

  • 如果x=1或者x=n-1,只需要将nums中第一个元素减小(最差到Integer.MIN_VALUE),或者最后一个元素增大总能满足要求;
  • 如果1<x<n-1,若将nums[x]变大必须要求nums[x-1]<=nums[x+1];
  • 若将nums[x-1]变小,须要求nums[x-2]<=nums[x];

3、出现超过1次的下降,肯定不同只通过调整一个元素完成要求,返回false。

整体代码:

public boolean checkPossibility(int[] nums) {
    int n = nums.length;
    if (n <= 1) return true;
    int down = 0;
    for (int i = 1; i < n; i++) {
        if (nums[i] < nums[i - 1]) {
            down++;
            if (down > 1) {
                return false;
            }
            if (i > 1 && i < n - 1 && nums[i - 1] > nums[i + 1] && nums[i - 2] > nums[i]) {
                return false;
            }
        }
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值