算法笔记之动态规划——等差数列划分 II - 子序列

2021-12-13  本文已影响0人  简单一点点

利用动态规划处理序列问题,很经典的题目,记录一下。

题目描述

LeetCode446. 等差数列划分 II - 子序列

给你一个整数数组 nums ,返回 nums 中所有 等差子序列 的数目。

如果一个序列中 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该序列为等差序列。

数组中的子序列是从数组中删除一些元素(也可能不删除)得到的一个序列。

例如,[2,5,10] 是 [1,2,1,2,4,1,5,10] 的一个子序列。

思路分析

首先我们新增一个定义,把只有2个元素的序列称为弱等差序列,弱等差序列虽然不是等差序列,当时它只要增加元素就会变成等差序列。

这样我们可以二重遍历元素,针对每个元素,求它和之前元素的弱等差序列并进行记录,如果前面已经存在相同差的弱等差序列,则添加一个元素后,一定是等差序列,我们就可以对结果加1。

当前元素每个弱等差序列元素数量等于已有的元素(也许之前存在多个相同元素)加上前一个元素的相同弱等差序列的元素数量再加上1(前一个元素和本元素组成的弱等差序列)。

Java代码

class Solution {
    public int numberOfArithmeticSlices(int[] nums) {
        if(nums.length <= 2) {
            return 0;
        }
        // 哈希表记录每个元素的弱等差数列
        // 键是相邻元素之差,值是序列中元素数量
        Map<Long, Integer>[] dp = new Map[nums.length];       
        for(int i = 0; i < dp.length; i++) {
            dp[i] = new HashMap<Long, Integer>();
        }

        int r = 0;
        // 二重循环遍历
        for(int i = 1; i < nums.length; i++) {
            for(int j = 0; j < i; j++) {
                Long d = (long)nums[i] - nums[j];
                int c = dp[j].getOrDefault(d, 0);
                r += c;
                int c2 = dp[i].getOrDefault(d, 0);
                // 注意这里还要加一个弱等差数列
                dp[i].put(d, c2 + c + 1);
            }
        }
        return r;
    }
}
上一篇下一篇

猜你喜欢

热点阅读