[DP]413. Arithmetic Slices

本文介绍了一种算法,用于统计给定整数数组中的等差数列切片数量。通过对数组进行预处理并利用双指针技巧,该算法能够高效地找出所有符合等差条件的子序列。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

A sequence of number 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 sequence:

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 slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N.

A slice (P, Q) of array A is called arithmetic if the sequence:
A[P], A[p + 1], ..., A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q.

The function should return the number of arithmetic slices in the array A.


Example:

A = [1, 2, 3, 4]

return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] itself.


题目分析:

1、根据题目定义,一个等差数列的长度至少为3。对于给出的数列,我们需要统计其中包含的等差数列的数量。

2、很明显对于长度为0[NULL]、1、2的数列,其不可能包含等差数列。对于长度大于等于3的数列,若其整个为一个等差数列,那么它所包含的等差数列数量N计算方法为(假设起长度为n ≥ 3):N = 1 + 2 + 3 + 4 + ……+ (n - 2)= (n - 1)(n - 2)/ 2,原理为分别其中统计长度为3、4、5……n的等差数列组合即可。对于长度为n ≥ 3但并非整个为等差数列的数列而言,为了统计其中包含的等差数列数量,我们只需要求出其中所包含的最长等差数列的个数即可,也就是统计范围内的数列并不能将两端的数加入以生成更长的等差数列。如对于数列A[1、2、3、4、9、5、1、-3、9]而言,它包含两个最长等差数列[1、2、3、4]和[9、5、1、-3],分别包含3个等差子数列,那么整个数列A而言,它所包含的所有等差数列和为3 + 3 = 6个。

3、现在面临的问题是如何去找出数列中的所有最长等差数列。很明显任意两个不同的最长等差数列并不会相互重合,否则这两个数列可以合并。既然不会重合,那么我们就可以对数列A进行一次遍历来解决,只需要设置两个指示头尾下标的参数 start 和 end,初始化为0、1;若A[end + 1] - A[end] = A[end] - A[end - 1], 那么说明A[end + 1]满足前面数列的公差,则end ++继续判断,直至等式不成立表示A[end + 1]不满足前面等差数列的公差,则结束前面的最长等差数列的统计,如果你n = end - start + 1 ≥ 3,则找到了一个最长等差数列,计入统计,接下来开始下一次统计,即start = end, end += 1。

4、此题中采用另一种统计方法,即先对数列A作出预处理,新建数列sub统计每两个相邻数的差值,则在3中的判决等式不需要调用三个数列值,只需要判断sub中相邻两个数是否相等即可,且在统计过程中取消两个参数start和end,采用一个指示变量loc和计数变量countn即可。


代码:

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) {
        if(A.size() < 3)
            return 0;
        int sub[A.size() - 1];
        for(int i = 0; i < A.size() - 1; i++){
            sub[i] = A[i + 1] - A[i];
        }
        int count = 0;
        int loc = 0;
        while(loc < A.size() - 1){
            int subn = sub[loc];
            int countn = 1;
            while(loc < A.size() - 1){
                if(sub[loc] == subn)
                    countn ++;
                else break;
                loc ++;
            }
            if(countn >= 2){
                count += (countn-2)*(countn-1)/2;    
            }
            //loc ++;     //not need
        }
        return count;
    }
};

### 回答1: 这是Java中的一个异常,意思是需要进行四舍五入。通常是因为进行了除法运算,但结果不能被精确表示为一个整数或小数。解决方法是使用BigDecimal类进行精确计算,或者使用Math.round()方法进行四舍五入。 ### 回答2: java.lang.ArithmeticException: rounding necessary是Java中的一个异常。它表示在进行数值运算时,需要进行舍入操作。在Java中,当进行除法或四舍五入等运算时,如果结果不是一个整数,则需要进行舍入以获得最接近的整数或指定的小数位数。 这个异常通常发生在以下情况下: 1. 当进行除法运算时,如果除数不能整除被除数,则需要进行舍入才能得到结果。如果无法进行舍入操作,就会抛出该异常。 2. 当通过四舍五入方式将一个小数转换为整数或指定小数位数时,如果需要进行舍入操作才能得到结果,则会抛出该异常。 为了解决这个异常,我们可以采取以下措施: 1. 检查除法运算中的被除数和除数,确保能够整除,避免出现舍入错误。如果无法整除,则需要重新设计算法或找到其他解决方案。 2. 在进行四舍五入运算时,可以使用Java中的Math类提供的方法,如Math.round()来进行舍入操作。此外,还可以考虑使用BigDecimal类来处理精确的小数运算,它提供了很多可以进行舍入操作的方法。 总之,当我们在Java中遇到java.lang.ArithmeticException: rounding necessary异常时,表示在进行数值运算时需要进行舍入操作。要解决这个异常,我们需要检查除法运算中的被除数和除数,以及使用适当的方法进行舍入操作,保证结果的准确性。 ### 回答3: Java.lang.ArithmeticException: rounding necessary 是一个在Java中的异常类型。它表示在进行数值运算时需要进行四舍五入操作。 在进行数值运算时,可能会出现无法准确表示的结果,特别是涉及到浮点数和小数点的运算。由于计算机的内部表示方式有限,无法完美地表示所有的小数和浮点数。这就导致了某些运算结果的尾数部分可能无法精确表示,需要进行四舍五入操作。 当进行一个数值运算时,如果该运算需要进行四舍五入操作以确保结果的准确性,但是没有指示具体的四舍五入策略时,就会抛出 java.lang.ArithmeticException: rounding necessary 异常。 要解决这个异常,可以使用合适的四舍五入策略来确保数值运算的准确性。Java中提供了 BigDecimal 类来处理高精度的数值计算,它可以指定要使用的四舍五入策略。在进行数值运算时,可以使用 BigDecimal 类来处理数值,并指定需要使用的四舍五入策略,从而避免 java.lang.ArithmeticException: rounding necessary 异常的发生。 总之,解决 java.lang.ArithmeticException: rounding necessary 异常的方法是使用 BigDecimal 类来处理数值运算,并指定合适的四舍五入策略。这样可以确保数值运算的准确性,避免出现无法精确表示的结果导致的异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值