0665. 非递减数列

题目地址(665. 非递减数列)

题目描述

1
给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。
2
3
我们是这样定义一个非递减数列的: 对于数组中所有的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。
4
5
6
7
示例 1:
8
9
输入: nums = [4,2,3]
10
输出: true
11
解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。
12
13
14
示例 2:
15
16
输入: nums = [4,2,1]
17
输出: false
18
解释: 你不能在只改变一个元素的情况下将其变为非递减数列。
19
20
21
22
23
说明:
24
25
1 <= n <= 10 ^ 4
26
- 10 ^ 5 <= nums[i] <= 10 ^ 5
Copied!

前置知识

  • 数组
  • 贪心

公司

  • 暂无

思路

这道题简单就简单在它限定了在 最多 改变 1 个元素的情况下,如果不限定这个条件,让你求最少改变多少个数字,就有点难度了。
对于这道题来说,我们可以从左到右遍历数组 A, 如果 A[i-1] > A[i],我们找到了一个递减对。遍历过程中的递减对个数大于 1,则可提前返回 False。
于是,大家可能写出如下代码:
1
class Solution:
2
def checkPossibility(self, A: List[int]) -> bool:
3
count = 0
4
for i in range(1, len(A)):
5
if A[i] < A[i - 1]:
6
if count == 1: return False
7
count += 1
8
return True
Copied!
上面代码是有问题的,问题在于类似 [3,4,2,3] 的测试用例会无法通过。问题在于递减对的计算方式有问题。
对于 [3,4,2,3] 来说,其递减对不仅仅有 (4,2)。其实应该还包括 (4,3)。 这提示我们在这个时候应该将 2 修改为不小于前一项的数,也就是 4,此时数组为 [3,4,4,3] 。这样后续判断就会多一个(4,3) 递减对。
而如果是 [3,4,3,3],在这个例子中应该将索引为 1 的修改为 3,即 [3,3,3,3],而不是将索引为 2 的修改为 4,因为末尾数字越小,对形成递增序列越有利,这就是贪心的思想。代码上,我们没有必要修改前一项,而是假设 ta 已经被修改了即可。之所以可以假设被修改是因为题目只需要返回是否可组成非递减数列,而不需要返回具体的非递减数列是什么,这一点需要大家注意。
大家可以继续找几个测试用例,发现一下问题的规律。比如我找的几个用例: [4,2,3] [4,2,1] [1,2,1,2] [1,1,1,] []。这样就可以写代码了。

关键点

  • 考虑各种边界情况,贪心改变数组的值

代码

  • 语言支持:Python3
Python3 Code:
1
class Solution(object):
2
def checkPossibility(self, A):
3
N = len(A)
4
count = 0
5
for i in range(1, N):
6
if A[i] < A[i - 1]:
7
count += 1
8
if count > 1:
9
return False
10
# [4,2,3] [4,2,1] [1,2,1,2] [1,1,1,] []
11
if i >= 2 and A[i] < A[i - 2]:
12
A[i] = A[i - 1]
13
14
return True
Copied!
复杂度分析
令 n 为数组长度。
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$

相关专题

  • 最长上升子序列
此题解由 力扣刷题插件 自动生成。
力扣的小伙伴可以关注我,这样就会第一时间收到我的动态啦~
以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。