2021-08-17

题目详情

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/non-decreasing-array

解法思路

思路一:

思路分析

 * 解题思路:什么样的数列才能够最多改变一个值的情况下
 *          变为非递减呢?
 * 我们观察发现如果在数组中,第i个值比第i+1个值大的情
 * 况出现次数小于等于一次,那么这个数组就有可能满足改
 * 变一个值成为非递减数列。
 * 首先没有这种情况出现时,已经是非递减数列;当出现这
 * 种情况多于一次时,至少需要改两个值才行。所以我们可
 * 以遍历统计这种情况出现的次数,如果出现多于一次,直
 * 接return false
 * 那么只出现一次的情况需要改几个值能满足呢?笔者的思
 * 路是,进行正向遍历,对于出现这种情况的第i个元素,他
 * 是比后一个大,也比前一个大的,笔者把这个元素变为第i
 * -1个元素的值,这样就不会比前面的元素小,但是这样一
 * 定能满足吗?不一定!例如:[3,4,2,2],把4变为3后也不
 * 行因为比后面大;如果变为前一个元素不行,那么就变成后
 * 一个元素吧,只有这两种极端选择了,变为[3,2,2,2]呢?
 * 很显然也不行,所以流程有了:
 * 1.正向遍历,先把第i个元素变为第i-1个元素,设立flag
 * 2.接着,第一种方案行不通后将第i个元素变为第i+1个元
 * 素,成功就返回true,失败则返回false

代码

class Solution {
    public boolean checkPossibility(int[] nums) {
        //首先进行遍历筛选,只有数组中后一个比前一个大的个数小于等于1的
        //数组才可能变为递减数列
        int num_ill = 0;
        boolean flag1 = false;
        boolean flag2 = false;
        int item;
        for(int i = 0;i<nums.length-1;i++){
            if(nums[i]>nums[i+1]){num_ill++;}
        }
        if(num_ill==1){//满足条件进行判断
            //先进行正向判断,对于正向不满足的把第i-1个元素变为第i-2个元素
            //的值,如果改变后满足了就可
            for(int i = 0;i<nums.length-1;i++){
            if(nums[i]>nums[i+1])
            {if(i!=0){item = nums[i-1];}
            else{item = 0;}
            if(item<=nums[i+1]){
                flag1 = true;
            }
            //break;//只判断一次就退出
            if(!flag1){
                if(i!=nums.length-2){
                    item = nums[i+2];
                    if(item>=nums[i]){flag2 = true;}
                }else{
                    flag2 = true;
                }
            }
            break;
            }
        }
        return flag1||flag2;
        }
        else if(num_ill == 0){return true;}
        else{return false;}
    }
}

方案分析

 *该方案需要两次遍历,时间复杂度为O(n^2),可以考虑将第二次遍历
 *放入第一次中,时间复杂度为O(n)

思路二

思路分析

 * 基本思路同方案一,但是思路二发现对于数组[3,4,2,2],第二个位
 * 置的2小于第0个位置的3,需要将这个值变为前一个值4;如果现在数
 * 组变为[3,4,3,3],那么这个数组只需要把第1个位置的4变为3即可;
 * 所以,总结出规律,对于i+1位置小于i-1位置的,需要更新第i+1个元
 * 素为第i个位置的元素的值,这样才可以大于等于前一个位置,后续再
 * 接着判断满不满足。此种方法可以很好的把遍历集成 

代码

class Solution {
    public boolean checkPossibility(int[] nums) {
        int n = nums.length, cnt = 0;
        for (int i = 0; i < n - 1; ++i) {
            int x = nums[i], y = nums[i + 1];
            if (x > y) {
                cnt++;
                if (cnt > 1) {
                    return false;
                }
                if (i > 0 && y < nums[i - 1]) {
                    nums[i + 1] = x;
                }
            }
        }
        return true;
    }
}

方案分析

 *该方案并没有像方案一那样,上来就开始变值判断,而是总结出了需
 *要和不需要判断的条件,即第i+1个值对比第i-1个值的关系,比较巧
 *妙,时间复杂度为O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值