Leetcode 665
题目描述
Given an array with n integers, your task is to check if it could become non-decreasing by modifying at most 1 element.
We define an array is non-decreasing if array[i] <= array[i + 1] holds for every i (1 <= i < n).
题目分析
我们要做的是:判断一个数组:能否至多只移动一个数字,就能够使得该数组变为不减数组。
来思考符合题目要求的数组应该具有怎样的特征?
由于题目要求不降数组,我们可以先遍历数组,将每个数与它右侧的数进行比较,若发生了“降”,则记录降的次数加1。
首先,已经有序,不降的数组显然是满足题目要求的,此时数组中“降”的次数为0。
(由于这一个一开始没有注意到,结果搞了半天都没有AC)
其次,如果这一个数组可以通过只移动一个数字的方式就能恢复成不降序列,该数组发生“降”的次数必然是1,如果不是1的话,假设是2,那么就有两个位置都发生了“降”的情况。这时候如果仅仅移动一个数字,只可能将一个“降”消去,但是另一个降是不可能消失的。
因此,我们先确认,满足这样的数组的一个必要条件是dec_time == 0
,这个在代码中可以了解他的意思。
但是这样的条件还不够,我们仍然可以找到这样的数组,它满足dec_time == 0
,但是仅移动一个数字是不能够将数组恢复成不降序列的。如下面的例子:
我们可以进一步思考符合题目要求的数组需要满足的特征。仅移动一个数组便能恢复,说明该数组只有一个数字是无序的,并且将这个数字从数组中拿出后,新的数组应该要保持有序不降。很显然,我们现在的必要条件,并不能保证新的数组仍能有序不降。
在计算dec_time
时,我们可以找到数组中第一个降序的数对的位置。设这个数对中较大的数的索引为index
。
因为现在的条件,并不足以让我们判断失序的两个数中是哪一个数导致了数组的失序,这时候可以将这样的数组分成两类来讨论:
- 失序的数比周围的数大
- 失序的数比周围的数小
情况1:大
对于失序的数比周围的数大的情况,那么这个时候,失序的数应该是索引index
对应的数字,那么当我将这个数字从数组中拿出来时,这个数组应该是不降的,因此我们得到
情况2:小
对失序的数比周围的数小的情况,这时我们可以判断失序的数应该是索引index+1
对应的数字。同样由于新数组是不降的,因此得到:
将以上的情况判断后,再将一些边界条件处理一下(如失序的数位于数组首尾的情况),就可以完成这一道题目了。
代码展示
class Solution:
def checkPossibility(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
dec_time = 0
index = 0
for i in range(0, len(nums)-1):
if nums[i] > nums[i+1]:
dec_time += 1
index = i
if dec_time == 0:
return True
if dec_time == 1:
if index == 0 or index == len(nums)-2:
return True
if nums[index-1]<=nums[index+1]:
return True
if nums[index] <= nums[index+2]:
return True
return False
感想
卡了很久,后来发现自己没有处理数组原本就有序的情况,傻逼了。