Leetcode 413. Arithmetic Slices

介绍一种高效算法,使用滑动窗口方法计算给定数组中连续且满足算术特性的子数组数量。该算法避免了传统的枚举做法,通过动态调整窗口两端来减少时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

             大概题意:规定一个数组是算术的,当且仅当满足以下两个条件:元素个数大于等于3,且任意两个相邻元素之间的差(后一个减前一个)相等。给定一个数组,求连续的且满足算术的子数组的个数。

            这道题如果采取枚举起点和终点,然后再判断正确性的做法,枚举的时间复杂度为O(n2),判断最坏的情况下是O(n),则时间复杂度为O(n3),太大了,显然会超时。需要采取其它的更高效的做法。

             我们很容易就能发现一个特性,如果一个数组子序列不是算术的,则包含它的任何数组序列也不是算术的。知道了这个特征,我们可以省去很多枚举所消耗的时间。

            这道题可以采用“滑动窗口的做法”。设置左端点P,和右端点Q。初始[P, Q] 是算术的。然后将Q向右滑动一格,若依然是算术的,则增加算术连续子序列的个数;否则,将P滑动到Q的前一格,因为包含之前的[P,Q] 的子序列一定不是算术的。判断新序列是否依然是算术的的时间复杂度为O(C),因为只要先记录下前面子序列两两之间的差值(只需记下一个,因为是算术的),然后在与新加入元素与其前一个元素的差做比较即可。

            注意当[P, Q] 满足算术的的时候,满足的序列的总数要加上 Q - P - 1 ,因为[ P + 1, Q],  [P+2, Q], ... , [Q-2, Q] 同样是满足算术的。

            因为P和Q都至多分别遍历0 ~ n-1 一次,所以时间复杂度为O(n),具体代码如下:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) {
        int cnt = 0 ;
        if (A.size() <= 2) return 0 ;
        int P = 0, Q = 2, n = A.size() ;
        int dist = A[P+1] - A[P] ;
        
        while (P < n && Q < n) {
        	while (A[Q] - A[Q-1] == dist &&  Q < n) {
        		cnt += Q - P - 1 ; Q ++ ;
        	}
        	P = Q - 1 ;
        	dist = A[Q] - A[P] ;
        	Q++ ;
        }
        return cnt ;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值