LeetCode#413 Arithmetic Slices题解(C++版)

来源:互联网 发布:如何识别淘宝客链接 编辑:程序博客网 时间:2024/06/14 01:02

题干

这里写图片描述

原题网址:
https://leetcode.com/problems/arithmetic-slices/description/

题干解析

给你一个数列,要你算出他有多少个等差子序列(等差子序列的长度应该大于等于3)。

知识点

动态规划

难度

中等

解题思路

本题可用动态规划求解,思路有点类似于动态规划的经典题目之求回文子串个数(注意,因为本题要求的是连续的,所以是子串不是子序列),如果熟悉求回文子串的话,修改一下就可以解本道题了。
首先用指针进行动态申请内存,生成一个二维的标志子序列是否为等差的表,行号表示这个子序列的第一个数字在原vector里面的下标,而“列号+i”表示子序列最后一个数字在原vector里面的值。注意这里,我不是直接用列号表示子序列最后一个数字的下标,而是用列号+i,比如:第i行的列号为0的数字,代表着以第i个数字为起始,以第0+i个,也就是第i个数字为截止的长度为1的子序列;第i行的列号为1的数字,代表着以第i个数字为起始,以第i+1个数字为截止的长度为2的子序列。之所以这样做,是因为要节省空间。倘若我直接用列号表示子序列最后一个数字在原序列中的下标的话,我们知道最后一个数字的下标肯定大于等于第一个数字下标,那么那些列号小于行号的就相当于浪费掉了,浪费了将近一半的空间,而且博主亲测这样交上去的话会超出题目的内存限制=。=通过遍历,计算出各个子序列是否为等差,在写代码时这里要注意避免重复计算,其他的就没有什么太大的问题。具体代码如下。

代码

int** is_or_not;  // 标志数列是否为等差的class Solution {public:    void is_slices(vector<int>& A, int i, int j) { // 计算A中的第i个到第j+i个数组成的数列是否为等差序列        if (j < 2) {  // 如果长度小于3,使其为真            is_or_not[i][j] = 1;            return;        }        if (is_or_not[i][j] != -1) {  // 如果之前已经计算过了,不再重复计算            return;        } else {            if (is_or_not[i + 1][j - 1] == -1) {  // 如果该序列去掉头尾数字的子序列没有计算过,先计算一下                is_slices(A, i + 1, j - 1);            }            if (is_or_not[i + 1][j - 1] == 0) {  // 如果他的子序列不是等差的,那么他也不是等差的                is_or_not[i][j] = 0;            } else if (is_or_not[i + 1][j - 1] == 1) { //如果他的子序列是等差的                if ((A[i] - A[i + 1]) == (A[i + 1] - A[i + 2]) && (A[j + i] - A[j + i - 1]) == (A[j + i - 1] - A[j + i - 2])) {  //如果他的头尾数字分别与其内部邻居的差值,等于他的等差子序列公差,则他也是等差的                    is_or_not[i][j] = 1;                } else {                    is_or_not[i][j] = 0;                }            }            return;        }    }    int numberOfArithmeticSlices(vector<int>& A) {        // 动态申请内存        is_or_not = new int*[A.size()];        for (int i = 0; i < A.size(); i++) {            is_or_not[i] = new int[A.size() - i];  // 因为如果这里长度也为A.size()的话会超出内存限制,所以进行了小处理(减少了内存)            for (int j = 0; j < A.size() - i; j++) {                is_or_not[i][j] = -1; // 初始化            }        }        //遍历计算各个子数列是否为等差的        for (int i = 0; i <A.size(); i++) {            for (int j = 0; j < A.size() - i; j++) {                is_slices(A, i, j);            }        }        // 算出等差子序列的个数        int ans = 0;        for (int i = 0; i < A.size(); i++) {            for (int j = 0; j < A.size() - i; j++) {                if (is_or_not[i][j] == 1 && j >= 2) {                    ans++;                }            }        }        // 释放动态申请的内存        for (int i = 0; i < A.size(); i++) {            delete is_or_not[i];        }        delete is_or_not;        return ans;  // 返回答案    }};
原创粉丝点击