添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

leetcode每日一题之665. 非递减数列

本题虽然说是简单题,但是并不简单,bebug了数十次,没看错,确实是数十次,才ac。有种面向测试用例编程的感觉了。

好在最后提交的总体思路和官方题解差不多,也不枉我熬一宿了,是的,这个题目做了好久的。不过相对官方题解,有不少的冗余,在注释里会提到。

大体思路就是每次遇到一组前大后小的两个数,就记录一下,然后对其进行处理(这是关键),如果遇到第二次这样的情况,那就说明不能通过一次修改将其变为非递减序列,返回false。

要对这两个数进行处理,就要考虑,是处理改变前一个数还是改变后一一个数,什么情况下怎么改变;由于我们一直比较的是前后两个数,如果是前一个数需要修改,那么对后续的比较不产生影响,就不做处理,因此我们只考虑后一个数需要被修改的情况。

因为我们修改之后要保证前后这两数是非递减,比如当前不符合条件的两个数是a[i]和a[i+1],因为修改之后不能破坏a[i-1]和a[i]的非递减关系,如果a[i-1]大于a[i+1],那么只能将a[i+1]置为a[i],如果将a[i]修改为a[i+1],则破坏了a[i-1]和a[i]的非递减关系。另一种情况,如果a[i-1]小于等于a[i+1],此时为了尽可能保持后面是递增序列,则a[i+1]要尽可能小,所以不能增大a[i+1],所以将a[i]修改为a[i+1]或者a[i-1]比较合适,更准确的话,a[i]也要尽可能小,但是a[i]已经不会对后面的结果造成影响,因为以后就是a[i+1]以后的比较了。

综上,我们只需要考虑需要修改a[i+1]的情况,并且确定如何修改a[i+1]

代码如下

class Solution {
public:
    bool checkPossibility(vector<int>& nums) {
        int n = nums.size(); 
        // if(n < 3)
        //     return true; // 此前代码中有a[2],所以要将长度小于3的数组直接返回
        // if(n == 3)
        //     if(nums[0] > nums[1] && nums[1] > nums[2])
        // 如果开头有连续三个递减,则直接返回false
        //         return false;
        int count = 0;
        for(int i = 0; i < n - 1; i++)
            if(nums[i] > nums[i + 1])
                count++;
                if(count > 1)
                    return false;
                if(i > 0) // 如果第0和第1两位逆序,不进行操作,后面再出现一个逆序就为false
                // 因为第0个数取值取决于后面,整个序列能否非递减也是取决于后面
                // 如果是第1位和后面出现逆序,需要操作一次,后面再出现一个逆序就为false
                    if(nums[i - 1] > nums[i + 1])
                        nums[i + 1] = nums[i];
                    // else    
                    //      nums[i] = nums[i - 1]; // 可以不处理
                // else // i等于0的时候,如果a[0]>a[1],肯定是将a[0]置为a[1],修改a[0]对后面的判断没有影响,所以不需要操作
                //     if(nums[0] > nums[2])
                //         nums[0] = nums[1];