LeetCode665- 非递减数列 | 算法练习系列

137 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情

前言

我发现一般越是简短的题目越容易做错,总是少考虑情况,今天来一道中等难度的数组相关的题目,先看题目吧

题目描述

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

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

 

示例 1:

输入: nums = [4,2,3]

输出: true

解释: 你可以通过把第一个 4 变成 1 来使得它成为一个非递减数列。

示例 2:

输入: nums = [4,2,1]

输出: false

解释: 你不能在只改变一个元素的情况下将其变为非递减数列。

解题思路

这一题的关键点在于以下几点:

  • 首先是只能更改一个数字来达到非递减减数列,这时候假设遇到了一个数组是[2,4,3],这时只要把4改为3就满足条件了
  • 还有一种情况是,加入遇到了一个数组是[3,6,1],这时候如果按上边的方法来处理就会变成[3,1,1],这就不符合要求了,但如果改变成[3,6,6]就是符合要求的,所以当发现前一项大于后一项时要分为两种情况来处理
  • 还需要设置一个count,用来标记已经进行了几次更改,如果大于0直接返回false即可 代码如下:
/**
 * @param {number[]} nums
 * @return {boolean}
 */
var checkPossibility = function (nums) {
    let count = 0
    let midValue = 0 //用来记录改变值之前的nums[i]
    for (let i = 0; i < nums.length - 1; i++) {
        if (nums[i] > nums[i + 1]) {
            if (count > 0) {
                return false
            } else {
                midValue = nums[i]
                nums[i] = nums[i + 1] //这里就是第一种处理方式,当遇到前一项大于后一项的时候,直接把当前项改为后一项的值
                //这里要特别注意,上述的赋值操作可能引出第二种情况,也就是思路中说的第二点,改变的值可能又小于了前一项,所以要做特殊处理
                if (nums[i] < (i - 1 >= 0 ? nums[i - 1] : 0)) {
                    nums[i + 1] = midValue
                    nums[i] = midValue
                    if (!count) {
                        count++
                    } else {
                        return false
                    }
                    continue
                } else {
                    if (!count) {
                        count++
                    } else {
                        return false
                    }
                }
            }


        }


    }
    return true
};

运行结果如下图:

image.png

总结

做之前总情况考虑不全,妥妥的面向测试数据编程,啥时候才能做题之前把情况都考虑清楚啊,唉