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个了
但是以现在的水平推测要判断四个点。。。还是有点难