446. Arithmetic Slices II - Subsequence

题目:A sequence of numbers is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.A zero-indexed array A consisting of N numbers is given. A subsequence slice of that array is any sequence of integers (P0, P1, ..., Pk) such that 0 ≤ P0 < P1 < ... < Pk < N. subsequence slice (P0, P1, ..., Pk) of array A is called arithmetic if the sequence A[P0], A[P1], ..., A[Pk-1], A[Pk] is arithmetic. In particular, this means that k ≥ 2. The function should return the number of arithmetic subsequence slices in the array A.

The input contains N integers. Every integer is in the range of -231 and 231-1 and 0 ≤ N ≤ 1000. The output is guaranteed to be less than 231-1.

原题目太长了,大意就是定义了等差数列,是一个长度大于等于3的数列,给定一个数列,找出里面等差数列的个数,等差数列的长度大于等于3就可以,数列可以不连续。注意整数的范围是 -231 到 231-1。给定数列A的长度N范围是0 ≤ N ≤ 1000。


思路:之前做了一道题413 Arthmetic Slices,那道题严格要求等差数列是连续的,于是用一个一维数组dp[n]表示以第n个数字为结尾的等差数列个数。初始化dp全为0。如果A[2]-A[1]=A[1]-A[0],那么dp[2] = 1。令i从3遍历到n,检查A[i]-A[i-1]和A[i-1]-A[i-2]是否相等,如果不相等,那么dp[i]不改变还是0,因为第A[I]和A[I-1]、A[I-2]连续的3个数不能构成等差数列。如果相等,那么dp[i] = dp[i--1]+1,之前以i-1为结尾的数列再加上A[i]又能构成等差数列,所以dp[i]比dp[i-1]多1。最后将dp的所有数字相加就能得到结果。

这道题与上面那一题的差别是数列可以不连续,也就是每个数字可以和前面不同的数字组成等差数列,那就会有不同的差,所以需要在上一题的基础上给dp增加一维记录差。dp[i][diff]表示以A[i]结尾,与前面数字差别为diff的数列个数。i从0遍历到n,j从0遍历到i,计算每一个A[i]-A[j]的值为diff,那么以i为结尾,diff为差的数列个数就加1,如果dp[j][diff]不为0,说明以j为结尾,diff为差的数列存在,这时候就至少有3个数可以组成等差数列(i,j,j前面与j差为diff的数),以j为结尾,diff为差的每一个等差数列再加上A[i]之后,都可以组成新的等差数列,所以dp[i][diff] = dp[i][diff] + dp[j][diff]。最后将所有的dp[i][diff]相加就得到结果了。特别注意这题整数的范围 -231 到 231-1,所以要用long型。


class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) {
        int n = A.size();
        vector<unordered_map<int,int> > dp(n);//长度为n的vector,每一个值是不同的diff对应的数列个数
        int res = 0;
        for(int i = 0; i < n; ++i)
        {
            for(int j = 0; j < i; ++j)
            {
                long diff = (long)A[i] - (long)A[j];
                if(diff > INT_MAX || diff < INT_MIN)//判断是否越界
                    continue;
                diff = (int)diff;
                if(!dp[i].count(diff))//空处理
                    dp[i][diff] = 0;
                dp[i][diff]++;
                if(dp[j].count(diff) != 0)//前面有数字能组成等差数列
                {
                    res += dp[j][diff];//累加结果
                    dp[i][diff] += dp[j][diff];//状态转移
                }
            }
        }
        return res;
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值