446. Arithmetic Slices II - Subsequence

446. Arithmetic Slices II - Subsequence


difference between any two consecutive elements is the same.

For example, these are arithmetic sequences:

1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
The following sequence is not arithmetic.

1, 1, 2, 5, 7

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.

A 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.

Example:

Input: [2, 4, 6, 8, 10]

Output: 7

Explanation:
All arithmetic subsequence slices are:
[2,4,6]
[4,6,8]
[6,8,10]
[2,4,6,8]
[4,6,8,10]
[2,4,6,8,10]
[2,6,10]

方法1: dynamic programming

grandynag: https://www.cnblogs.com/grandyang/p/6057934.html
思路:

这道题有一点像之前的frog jump,因为dp的转移式需要根据和上一个数的差值来遍历一个hashmap查找。这道题还需要遍历当前dp位置之前的所有数字,计算两数差值,并且在j中查找有没有这个diff。如果有的话,说明之前至少有两个数字形成了相同diff的sequence,那么现在的第三个数使得新的等差数列成立,dp[j][diff]应该被计入res。同时,这个数字应该被叠加至diff[i][diff]。注意是叠加不是diff[j][diff]:举个栗子,j = 2, dp[j][2] = 2, 分别为[2, 4, 6], [4, 6],dp[j][4] = 1, [2, 6],那么新的8会在此基础上产生什么样的改变?首先[2, 4, 6], [4, 6]被变成[2, 4, 6, 8]和[4, 6, 8],dp[i][2] += dp[j][2],同时,A[j]和A[i]本身形成了新的一对弱等差数列,因此再dp[i][diff] ++。当dp[j][diff]不存在时,这两个操作都加0,对结果没什么影响,所以overall, 转移式可以非常简单的表示为++dp[i][diff] = dp[j][diff]。这里的test case会有差值非常大的数字,比如接近int max和int min的两个数字连在一起,那么差值就会溢出整型范围。这里把difff暂时保存为long,先和整型范围比较一下,如果大于int max或小于int min, 由于题目规定了数字都是整型范围内的,因此不可能出现三个数字等差直接continue。否则需要再把difff换回整型,继续上面的做法。

易错点:

  1. (long) (A[i] - A[j]) 是没用的:(long) A[i] - A[j]才可以因为两个数字都是int的话,默认用int类中间值过度,还是会溢出,必须把其中一个变成long,才会默认用long过度。

Complexity

Time complexity: O(n^2)
Space complexity: O(n ^ 2)

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) {
        int res = 0;
        vector<unordered_map<int, int>> hash(A.size());
        
        for (int i = 0; i < A.size(); i++) {
            for (int j = 0; j < i; j++) {
                long difff = (long) A[i] - A[j];
                if (difff > INT_MAX || difff < INT_MIN) continue;
                int diff = (int) difff;
                
                // hash[i][diff] = hash[j][diff] + 1;
                // if (hash[i][diff] >= 2) {
                //    res += hash[j][diff];
                // }
                if (hash[j].count(diff)) {
                    res += hash[j][diff];
                }
                ++hash[i][diff] += hash[j][diff];
            }
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值