Skip to content

Latest commit

 

History

History
60 lines (43 loc) · 2.03 KB

File metadata and controls

60 lines (43 loc) · 2.03 KB

LC.446 等差数列划分 II - 子序列

https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/

题目描述

截屏0003-08-12 14 26 29

思路

👉 446. 等差数列划分 的升级版, 这也太难了吧。

动态规划 + 哈希表

子序列问题, 不要求连续, 就要想到用动态规划来解题。

动态规划的状态定义:

1. dp[i][diff] 代表以元素 nums[i] 结尾, 差为 diff 的个数。

2. 二维动态规划, 遍历 nums 中的元素对 (nums[i], nums[j])。

3. 动态转移方程: dp[i][diff] += dp[j][diff] + 1。

    这里为什么是 += 呢, 因为 dp[j][diff] 是以 diff 为公差的 以 nums[j] 结尾的子序列的个数。
    
    而现在要在这一堆子序列后面加上一个 nums[i]。
    
    比如 nums = [2, 4, 6, 8, 10]
    
    以数字 8 位结尾的公差为 2 的子序列一共有 2 个, 分别是 [4, 6, 8], [2, 4, 6, 8]。
    
    现在数字 10 要加到以 8 结尾公差为 2 的子序列后面, 就有了 [4, 6, 8, 10] 和 [2, 4, 6, 8, 10] 和新的 [6, 8, 10]。
    
    所以要 += 。

4. 题目要求至少有三个元素, i, j 和 diff 正好就是三个元素。

参考力扣官方解答, 二维动态规划我还能做几道简单的, 难的真的就gg了。

代码

class Solution:
    def numberOfArithmeticSlices(self, nums: [int]) -> int:
        '''
        dp = {index: {diff: count}}
        '''
        dp = [collections.defaultdict(int) for _ in nums]
        ans = 0
        for i in range(len(nums)):
            for j in range(i):
                diff = nums[i] - nums[j]
                dp[i][diff] += dp[j][diff] + 1
                if dp[j][diff]:
                    ans += dp[j][diff]
        return ans

复杂度分析

  • 时间复杂度: O(n^2)
  • 空间复杂度: O(n^2)