446. Arithmetic Slices II - Subsequence

37 篇文章 0 订阅
17 篇文章 0 订阅

原题网址:https://leetcode.com/problems/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.

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.

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]

思路:动态规划,使用哈希映射保存差值的计数器。

方法一:分别保存两个数的差值计数器和三个以上的差值计数器,此方法会超时。

public class Solution {
    public int numberOfArithmeticSlices(int[] A) {
        Map<Long, Integer>[] pairCounts = new Map[A.length];
        for(int i = 0; i < A.length; i++) pairCounts[i] = new HashMap<>();
        Map<Long, Integer>[] seqCounts = new Map[A.length];
        for(int i = 0; i < A.length; i++) seqCounts[i] = new HashMap<>();
        int numbers = 0;
        for(int i = 0; i < A.length - 2; i++) {
            for(int j = i + 1; j < A.length - 1; j++) {
                long diff = (long)A[j] - A[i];
                Integer count = pairCounts[j].getOrDefault(diff, 0);
                pairCounts[j].put(diff, ++count);
            }
        }
        for(int i = 1; i < A.length - 1; i++) {
            for(int j = i + 1; j < A.length; j++) {
                long diff = (long)A[j] - A[i];
                Integer pCountI = pairCounts[i].getOrDefault(diff, 0);
                Integer sCountI = seqCounts[i].getOrDefault(diff, 0);
                Integer sCountJ = seqCounts[j].getOrDefault(diff, 0);
                if (pCountI + sCountI + sCountJ > 0) {
                    seqCounts[j].put(diff, pCountI + sCountI + sCountJ);
                    numbers += pCountI + sCountI;
                }
            }
        }
        return numbers;
    }
}

方法二:参考 https://discuss.leetcode.com/topic/67413/detailed-explanation-for-java-o-n-2-solution,精妙之处在于解决了一对数字和三个以上数字的差值计数器问题。

public class Solution {
    public int numberOfArithmeticSlices(int[] A) {
        int result = 0;
        Map<Integer, Integer>[] counts = new Map[A.length];
        for(int i = 0; i < A.length; i++) {
            counts[i] = new HashMap<>();
            for(int j = 0; j < i; j++) {
                long diff = (long)A[i] - A[j];
                if (diff <= Integer.MIN_VALUE || diff > Integer.MAX_VALUE) continue;
                int ci = counts[i].getOrDefault((int)diff, 0);
                int cj = counts[j].getOrDefault((int)diff, 0);
                counts[i].put((int)diff, ci + cj + 1);
                result += cj;
            }
        }
        return result;
    }
}

C++代码:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) {
        int res = 0;
        vector<unordered_map<int, int>> counts(A.size());
        for(int i = 1; i < A.size(); i++) {
            for(int j = 0; j < i; j++) {
                if((long)A[i] - (long)A[j] > INT_MAX || (long)A[i] - (long)A[j] < INT_MIN) continue;// do not ignore this step, it will help you save time & space to pass OJ.
                int diff = A[i] - A[j];
                int ci = counts[i].find(diff) == counts[i].end() ? 0 : counts[i][diff];
                int cj = counts[j].find(diff) == counts[j].end() ? 0 : counts[j][diff];
                counts[i][diff] = ci + cj + 1;
                res += cj;
            }
        }
        return res;
    }
};

Python代码:

class Solution(object):
    def numberOfArithmeticSlices(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        res = 0
        counts = {}
        for i in range(len(A)):
            counts[i] = {}
            for j in range(i):
                diff = A[i] - A[j]
                ci = counts[i][diff] if diff in counts[i] else 0
                cj = counts[j][diff] if diff in counts[j] else 0
                res += cj
                counts[i][diff] = ci + cj + 1
        return res
        

JavaScript代码:

/**
 * @param {number[]} A
 * @return {number}
 */
var numberOfArithmeticSlices = function(A) {
    var res = 0;
    var counts = [];
    for(i = 0; i < A.length; i++) {
        var countI = {};
        counts.push(countI);
        for(j = 0; j < i; j++) {
            if (A[i] - A[j] <=  Number.MIN_SAFE_INTEGER || A[i] - A[j] >=  Number.MAX_SAFE_INTEGER) continue;
            var diff = (A[i] - A[j]).toString();
            var ci = counts[i][diff] || 0;
            var cj = counts[j][diff] || 0;
            // console.log("i="+toString(i)+",j="+toString(j)+",diff="+diff+",ci="+toString(ci)+",cj="+toString(cj));
            counts[i][diff] = ci + cj + 1;
            res += cj;
        }
    }
    return res;
};

但我的JavaScript无法通过测试。





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值