LeetCode 413.Arithmetic Slices题解

版权声明:本文为博主原创文章,如需转载,请注明出处。 https://blog.csdn.net/BlueBlueSkyZ/article/details/80614712

题目

题目会给出一串数字序列,我们的任务是获取其中满足等差数列的子串。因为要满足等差数列,所以子串长度至少为3。

我的思路

我的想法是,既然要看是不是等差数列,那么差值肯定是必须的啦。所以先计算差值得diff数组。
diff
得到diff数组之后,我们可以清楚看到,有5个连续的-1。样例中,我们可以手工算出,长度为3的有4个,长度为4的有3个,长度为5的有2个,长度为6的有1个。诶,是不是很像累加呢?其实就可以用累加解决,得出5个连续相同差值,我们就累加到4,即得出n,累加到n-1。

这样我们的思路就很清晰了:

  1. 由输入数组得到差值数组diff
  2. 从差值数组中找到大于等于两个连续相同差值,保存栈中(其实无所谓什么容器,只要能不覆盖存入即可,我只是用着方便)
  3. 从栈中读取所有的数值,减一后进行累加操作,然后合并结果

代码实现(Java)

    public int numberOfArithmeticSlices(int[] A) {
        int numOfAS = 0;
        if(A.length != 0) {
            int diff[] = getDifference(A);

            Stack<Integer> stack = getConsecutiveNum(diff);
            while(!stack.empty()) {
                int consecutiveNum = stack.pop();
                numOfAS += accumulate(consecutiveNum-1);
            }
        }

        return numOfAS;
    }

    /**
     * 获取连续相同的差值
     * @param diff
     * @return
     */
    public Stack<Integer> getConsecutiveNum(int[] diff){

        Stack<Integer> stack = new Stack<Integer>();

        int count = 1;
        for(int i = 0; i < diff.length - 1; i++) {
            if( diff[i] == diff[i+1] ) {
                count++;
            } else {
                if(count >= 2) {
                    stack.push(count);
                    count = 1;
                }
            }
        }
        //运行到最后时还需判断一次
        if(count >= 2) {
            stack.push(count);
        }
        return stack;
    }
    /**
     * 获取公差
     * @param A
     * @return
     */
    public int[] getDifference(int[] A) {
        int[] diff = new int[A.length-1];
        for(int i = 0; i < diff.length; i++) {
            diff[i] = A[i] - A[i+1];
        }
        return diff;
    }

    /**
     * 累加计算
     * @param n
     * @return
     */
    public int accumulate(int n) {
        int result = 0;
        while(n != 0) {
            result += n;
            n--;
        }
//      System.out.println("result:" + result);
        return result;
    }

思考

我的方法其实是有点基于观察的,时间复杂度是O(n),但是可以看出系数应该是很大的。空间复杂度的话,讲道理还是开辟了不少空间,也是O(n)。
同时,这个方法还容易有坑,我调试了两次才过。第一次,是因为判断连续差值那边,运行到最后时漏了一个判断;第二次,没有考虑空数据集。

最后看了题解,大佬用了动态规划ac,贴上代码膜一下:

public class Solution {
    public int numberOfArithmeticSlices(int[] A) {
        int dp = 0;
        int sum = 0;
        for (int i = 2; i < A.length; i++) {
            if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) {
                dp = 1 + dp;
                sum += dp;
            } else
                dp = 0;
        }
        return sum;
    }
}

其他也还有不少不错的解法,大家也可以去Solution上看看。

猜你喜欢

转载自blog.csdn.net/BlueBlueSkyZ/article/details/80614712