IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> leetcode 446. 等差数列划分 II - 子序列 - 困难题目- 官方题解 - 动态规划 - DFS -> 正文阅读

[数据结构与算法]leetcode 446. 等差数列划分 II - 子序列 - 困难题目- 官方题解 - 动态规划 - DFS

题目来源:力扣(LeetCode)和传说
链接:https://leetcode-cn.com/problems
特别鸣谢:来自夸夸群的 醉笑陪公看落花@知乎王不懂不懂@知乎QFIUNE@csdn
感谢小伙伴们督促学习,一起进步

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

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

例如,[1, 3, 5, 7, 9]、[7, 7, 7, 7] 和 [3, -1, -5, -9] 都是等差序列。
再例如,[1, 1, 2, 5, 7] 不是等差序列。
数组中的子序列是从数组中删除一些元素(也可能不删除)得到的一个序列。

例如,[2,5,10] 是 [1,2,1,2,4,1,5,10] 的一个子序列。
题目数据保证答案是一个 32-bit 整数。

示例 1:

输入:nums = [2,4,6,8,10]
输出:7
解释:所有的等差子序列为:
[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]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence

官方题解分析

  • 用字典存储任意两个元素的差值
  • 如果这个等差之前被存储过,说明至少有三个元素,可以构成等差序列
  • 在前面构成的每个数列中增加一个元素,即可得到以当前元素结尾的等差数列

示意图如下:
动态转移数组 f[j][i] 表示以 nums[i] 结尾的动态数组个数+1
在这里插入图片描述

解题代码

class Solution:
    def numberOfArithmeticSlices(self, nums):
        def solve3(nums):
            f = [defaultdict(int) for _ in nums]
            ans = 0
            for i in range(len(nums)):
                for j in range(i):
                    d = nums[i]-nums[j]
                    ans += f[j][d]
                    f[i][d] += f[j][d]+1
            return ans
        
        return solve3(nums)

求子集,再求等差数列

先用交换的思想求子集 O(n!+(n-1)!+(n-2)!+… + 2! + 1),再判断子集是否是等差数列 O(n)

整体时间复杂度 O((n!+(n-1)!+(n-2)!+… + 2! + 1) * n)

优化

  • 加入备忘录,减少重复计算
  • 优化子集判断为O(1) , 深度遍历时,如果前面得到了[2,4,6],后面增加一个 10 的时候,只需要判断 4,6,10 是否等差,即,只需要判断一次
  • 交换位的前一个 i-1 位置比交换后位置j 的数字大,一定不能形成等差数列,直接跳过

优化之后的时间复杂度 O((2^n)-1)

交换的思想求子集

参考 leetcode 46 和47 . 全排列,两种生成树的方案来解决全排列问题
在这里插入图片描述

基础代码实现 - 超时

'''
超时 O((2^n)-1) * O(n)
'''

class Solution:
    def numberOfArithmeticSlices(self, nums):
        self.count = 0
        memor = set()
        def solve1(nums):
            nums.sort()
            dnums = [(v,i) for i,v in enumerate(nums)]
            DFS(dnums,0)
        def DFS(dnums,i):
            if i == len(dnums):return
            for j in range(i,len(nums)):
                if dnums[i][1] > dnums[j][1] or (i>0 and dnums[i-1][1]>dnums[j][1]):
                    continue
                dnums[i],dnums[j] = dnums[j],dnums[i]
                if i>=2 and tuple(dnums[:i+1]) not in memor and check(dnums,i):
                    self.count += 1
                    memor.add(tuple(dnums[:i+1]))
                DFS(dnums,i+1)
                dnums[i],dnums[j] = dnums[j],dnums[i]
        def check(dnums,i):
            for j in range(1,i):
                if dnums[j+1][0]-dnums[j][0] != dnums[j][0]-dnums[j-1][0]:
                    return False
            return True
        solve1(nums)
        return self.count

代码实现- 优化等差数列检查 - 还有点错误

'''
优化等差数列判断 - 超时
超时 O((2^n)-1) * O(1)
'''
class Solution:
    def numberOfArithmeticSlices(self, nums):
        self.count = 0
        memor = set()
        def solve1(nums):
            nums.sort()
            dnums = [(v,i) for i,v in enumerate(nums)]
            DFS(dnums,0,False)
        def DFS(dnums,i,dc):
            if i == len(dnums):return
            for j in range(i,len(nums)):
                if dnums[i][1] > dnums[j][1] or (i>0 and dnums[i-1][1]>dnums[j][1]):
                    continue
                dnums[i],dnums[j] = dnums[j],dnums[i]
                dc = check(dnums,i,dc)
                if i>=2 and tuple(dnums[:i+1]) not in memor and dc:
                    self.count += 1
                    memor.add(tuple(dnums[:i+1]))
                DFS(dnums,i+1,dc)
                dnums[i],dnums[j] = dnums[j],dnums[i]
        def check(dnums,i,dc):
            if not dc and i>2:return False
            return dnums[i][0]-dnums[i-1][0] == dnums[i-1][0]-dnums[i-2][0]
        solve1(nums)
        return self.count

求某一个起点开始能构成的等差数列 DFS

todo

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-13 12:32:05  更:2021-08-13 12:33:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:34:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码