Leetcode 413. Arithmetic Slices

来源:互联网 发布:unity3d pbrshader 编辑:程序博客网 时间:2024/05/22 04:33

             大概题意:规定一个数组是算术的,当且仅当满足以下两个条件:元素个数大于等于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 ;    }};



0 0