力扣2972 统计移除递增子数组的数目--枚举子数组

链接:https://leetcode.cn/problems/count-the-number-of-incremovable-subarrays-ii/description/

看视频加自己理解的,写一下思考过程

注意:子数组是连续的序列

所以保留下来的序列只能是单边的,不能是中间的

不能移除空数组,所以j>=i+2

第一步:选出最长的前缀递增子序列,设最后的那个数字的下标为i

第二步:ans+=i+2,认为是当要删的子序列是为整个数组的最后一个数时,可以有多少种删除方法

例如,对1 4 3 2 4 5 3 6这个数组,i指向1,即元素4,

当要删除的子序列的右端点固定为最后一个数字时,可以删除:

1)从i+1这个位置开始到最后一个数字(记为j)

2)从i开始到j

3)从i-1开始到j

4)...

5)重复上述过程,一直到i=0,一共有i+2个子序列可以删除

第三步:开始枚举,从最后一个元素开始,记为j,假设要删除的子序列的最后一个数字的下标是j-1,计算此时可以有多少种删除方法。因为子数组是连续的序列,所以j到n-1这一段也同样必须是递增的,在循环的时候要加上这个判断条件

1)如果下标j的数比下标i大,那么可以删除:

a.i+1到j-1

b.i到j-1

c.i-1到j-1

d....

e.0到j-1

一共i+2个子序列

此时ans+=i+2

2)如果下标j的数比下标i小或等于,将i向左移,直到nums[i]<nums[j],随后和第一种情况类似,ans+=i+2

这里本来我想取一个i_copy等于i的,后来发现不需要,因为j后面的那一段是递增的,如果当前这个j比i小,那么再往前走的时候必然也不存在一个j比当前的i大

此时要注意,向左移的过程,i不能小于等于0,如果出现这种情况,说明当前这个nums[j]比递增序列的所有值都小,那么就只能ans+=1,认为是计算删除掉了0到j-1这一段。

看过灵神的代码后,发现不需要执行ans+=1这种情况,因为如果i小于等于0了,那么此时i==-1,且不会再变化了,还是执行ans+=i+2是一样的+1,可以简化代码

出现了i==-1的情况后,说明已经不可能再找到一个中间的数组,删除这个数组后保留的元素是递增的,此时就只需要对j进行遍历,每次遍历就ans+=1

AC代码:

class Solution {
public:
    long long incremovableSubarrayCount(vector<int>& nums) {
        long long n=nums.size();
        long long i=0;
        while(i<n-1&&nums[i]<nums[i+1])
            i+=1;
        if(i==n-1)
        return n+(n*n-n)/2;
        long long ans = i+2;
        long long j=n-1;
        for(j;j==n-1||nums[j]<nums[j+1];j--){
            if(i>=0&&nums[j]>nums[i])
                ans+=i+2;
            else{
                while(i>=0&&nums[i]>=nums[j])
                    i-=1;
                ans+=i+2;
            }
        }
        return ans;
    }
};

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值