Leetcode_446_等差数列划分Ⅱ - 子序列_动态规划

就离谱,昨天还奶了一口这题要是从子数组改成子序列难度就大了,没想到今天就出来了orz

先看到数组长度1000,没跑了,动态规划 n2 做法。

核心在于,如果确定了两个数,那必然能确定以这两个数为尾部的一条等差数列。我们使用动态规划的思想,从长度为2开始逐步延长,每增加一个新的元素,数列条数要增加的量,即为以这个新元素为末尾元素,之前的所有元素中的一个为倒数第二个元素,所构成的等差数列的数量(这个值我们之前必然已经得到了)。想到这里,我们基本已经可以列出状态转移方程。需要注意的是,等差数列长度至少为3,也就是我们累加答案的数量应该是 dp[j].getOrDefault(diff,0) 。

class Solution {
    public int numberOfArithmeticSlices(int[] nums) {
        int ans = 0;
        int len = nums.length;
        // dp[i].get(j) 代表最后一位为i的等差数组,当公差为j的时候,长度>=3的等差数列个数
        Map<Long, Integer>[] dp = new Map[len];
        for (int i = 0; i < len; i++) {
            dp[i] = new HashMap<Long, Integer>();
        }

        // i是最后一个数的序号
        for (int i = 1; i < len; i++) {
            // j是倒数第二个数的序号
            for (int j = 0; j < i ; j++) {
                long diff = 1L * nums[i] - nums [j];
                int bef = dp[j].getOrDefault(diff,0);
                ans += bef;
                dp[i].put(diff,dp[i].getOrDefault(diff,0) + bef + 1);
            }
        }
        return ans;
    }
}

看了下面这位大佬的题解后,有了新的思路,他使用了list和map进行预处理,map.get[i]为数组中值为nums[i]的下标连成的链表。然后,通过确定末尾两个数,锁定倒数第三个数的值,然后去map里拿链表,如果链表中有多个数,则累加。
dp[i][j]的i和j就单纯代表最后两个数下标为nums中i和j时的总个数。

链接:https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/solution/tong-ge-lai-shua-ti-la-yi-ti-liang-jie-d-404p/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值