2.非递减数列

leetcode 非递减数列


难度 简单

 

 


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

我们是这样定义一个非递减数列的: 对于数组中所有的 i (1 <= i < n),满足 array[i] <= array[i + 1]

示例 1:

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

示例 2:

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

说明:  n 的范围为 [1, 10,000]。

数组名为nums

 

本题为简单题通过率最低的,好像也不难,通过率怎么不高呢?后来自己naive了

 

定义变量n=数组长度,total=0

 

一、思路:

 

1、第一次尝试

 

(1)如果n小于3,return true;

(2)如果n大于2

在i<n-1的前提下,如果n[i]>n[i+1],++total

如果total<2,return true

反之false(因为++total,再加上前面的,足够false条件了)

理所当然通过不了啦,卡在了{3,4,2,3}这个实例上

 

2、第二次尝试,对(2)判断条件的第一次修改

这次我把比较对象拓展到了i-1上

若0<i<n-1 且 nums[i]>nums[i+1],++total,如果还有n[i-1]>n[i+1],则返回false,(就像下图一样)

这样可以了吧?

{2,3,3,2,4}

-_-||,虽然nums[2]>nums[3],nums[1]>nums[3],但是n[1]=n[2]啊

看来nums[i-1]这个也要比较啊

 

改一下,nums[i-1]!=nums[i]且n[i-1]>n[i+1]就返回false?

不好有意思,{3,3,2,2}

微笑

 

3、第三次尝试

由于前面的教训,嫌疑对象已经从2个增加到4个了:

所以分类标准也改变了:

(1)n<3:return true;

(2)n=3:如果n[0]>[1]>[0],return false,反之return true

(3)n>3,比较这四个对象:

nums[i-1],nums[i],nums[i+1],nums[i+2]

在nums[i]>nums[i+1] 且 0<i<n-2的前提下,

保证这四个点里面最多一个不满足nums[i]<=nums[i+1](即nums[i]或nums[i+1]本身不满足),

就++total,

反之return false

。。。

嗯,好像不错,那要怎么实现呢?

①首先nums[i]>nums[i+1]已经是板上钉钉的了

其次我们默认nums[i-1]<=nums[i]

因为如果nums[i-1]>nums[i],那么total已经+1了,再加上nums[i]>nums[i+1]时total+1

不管这四个点符不符合要求,false是妥妥的!

干脆默认nums[i-1]<=nums[i]得了

 

②如果nums[i-1],nums[i],nums[i+2]满足nums[i]<=nums[i+1]

由①,nums[i]<nums[i+2]

 

③如果nums[i-1],nums[i+1],nums[i+2]

由①,nums[i-1]<nums[i+1]且nums[i-1]<nums[i+2]

不考虑nums[i+1]与nums[i+2],反正后面会比较的

 

④合并②③,得nums[i]<nums[i+2] || (nums[i+1]<nums[i+2] && nums[i-1]<nums[i+1])

又由①:因为nums[i-1]<nums[i],

所以nums[i-1]<nums[i+2]等价于nums[i]<nums[i+2]

 

综上:nums[i]<nums[i+2] || nums[i-1]<nums[i+1]时,++total就行了,不用返回false

但是我们想返回的是false,所以要求上面条件的对立面,

为nums[i-1]>nums[i+1] && nums[i]>nums[i+2]

 

(4)所以最终条件:

当n>3,nums[i]>nums[i+1] 且 0<i<n-2时,

如果nums[i-1]>nums[i+1] && nums[i]>nums[i+2],返回false

否则total++

 

最后total<2,true

否则false

不容易啊,终于成功了!

 

二:代码

class Solution {
    public boolean checkPossibility(int[] nums) {
        int total=0,n=nums.length;
        if(n>3){    //大于3
            for(int i=0;i<n-1;++i){
                if(nums[i]>nums[i+1]){     //如果nums[i]>nums[i+1]
                    ++total;//那么++total
                    if(i+2<n && i>0){      //如果能有nums[i-1],nums[i],nums[i+1],nums[i+2]四个点可以进行判断
                        if(nums[i-1]>nums[i+1] && nums[i]>nums[i+2]){//如果这四个点除nums[i]或nums[i+1]
                                                                      //其中一个以外的三个点不都是nums[i]<=nums[i+1]
                                   return false;//本来是++total,在加上之前的nums[i]>nums[i+1]++total,已经可以false了
                        }
                    }
                }
            }
        }
        if(n==3){    //等于3
            if(nums[0]>nums[1] && nums[1]>nums[2]){
                total=2;
            }
        }
        if(total<2){   //小于3
            return true;
        }
        return false;
    }

}

 

感觉这次有点靠蒙啊,如果四个还出问题估计我就该考虑5个了

但是以现在的水平推测要判断四个点。。。还是有点难

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值