https://leetcode-cn.com/problems/arithmetic-slices-ii-subsequence/solution/deng-chai-shu-lie-hua-fen-ii-zi-xu-lie-by-leetcode/

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

例如,以下数列为等差数列:

1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。

1, 1, 2, 5, 7

数组 A 包含 N 个数,且索引从 0 开始。该数组子序列将划分为整数序列 (P0, P1, ..., Pk),P 与 Q 是整数且满足 0 ≤ P0 < P1 < ... < Pk < N。

如果序列 A[P0],A[P1],...,A[Pk-1],A[Pk] 是等差的,那么数组 A 的子序列 (P0,P1,…,PK) 称为等差序列。值得注意的是,这意味着 k ≥ 2。

函数要返回数组 A 中所有等差子序列的个数。

输入包含 N 个整数。每个整数都在 -231 和 231-1 之间,另外 0 ≤ N ≤ 1000。保证输出小于 231-1。

示例:

输入:[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]

方法二:动态规划【通过】
直觉要决定一个等差数列,至少需要两个参数:序列的首(尾)项和公差。算法从这一点出发,我们可以简单地设计出状态:f[i][d] ,代表以 A[i] 结束且公差为 d 的等差数列个数。让我们来试着列出状态转移方程。假设我们想在现有的等差数列们的基础上添加一个新元素 A[i] 来得到新的子序列。只有当现有的等差数列最后一项加上公差等于 A[i] 时,才能够将该元素添加到等差数列后。于是,我们可以写出 关于A[i] 的状态转移方程:对于所有 j < i,f[i][A[i] - A[j]] += f[j][A[i] - A[j]]。这表示了添加新项得到新的等差数列的过程。但问题来了。初始时所有的 f[i][d] 都置为 0,如果一开始根本就没有子序列,怎么生成新的子序列呢?在等差数列的原定义中,子序列的长度至少为 3。这使得只有两个下标 i 和 j 时,很难生成新的序列。那么,能不能考虑将长度为 2 的序列纳入考虑呢?我们定义弱等差数列:弱等差数列 是至少有两个元素的子序列,任意两个连续元素的差相等。弱等差数列有两个十分有用的性质?对于任何 i, j (i != j),A[i] 和 A[j] 总能组成一个弱等差数列。若在弱等差数列后添加一个元素且保持等差,则一定得到一个等差数列。第二个性质很显而易见,因为弱等差数列和等差数列的唯一区别就是它们的长度。于是,我们可以修改状态的定义:f[i][d]代表以 A[i] 结束且公差为 d 的弱等差数列个数。现在状态转移方程就十分简单:对于所有 j < i,f[i][A[i] - A[j]] += (f[j][A[i] - A[j]] + 1)。这里的 1 是因为根据性质一,我们可以对 (i, j)生成一个新的弱等差数列。所有弱等差数列的数量即为 f[i][d]之和。但如何从中挑选出不弱的那些呢?有两种方法:其一,我们可以对真弱等差数列的数量进行直接计数。真弱等差数列即为长度为 2 的弱等差数列,故其数量为 (i, j) 对的格数,即为 \binom{n}{2} = \frac{n * (n - 1)}{2}。(
2
n
​   )=
2
n∗(n−1)
​   。其二,对于 f[i][A[i] - A[j]] += (f[j][A[i] - A[j]] + 1),f[j][A[i] - A[j]] 是现有的弱等差数列个数,而 1 是根据 A[i] 和 A[j] 新建的子序列。根据性质二,新增加的序列必为等差数列。故 f[j][A[i] - A[j]] 为新生成的等差数列的个数。可以用下面的示例来演示整个过程:[1, 1, 2, 3, 4, 5]计算上述序列的答案。对于第一个元素 1,前面没有元素,答案保持 0。对于第二个元素 1,该元素与上一个 1 可以组成公差 0 的弱等差数列: [1, 1]。对于第三个元素 2,它无法与唯一的弱等差数列 [1, 1] 合并,因此答案仍为 0。与上一个元素类似,它也可以形成新的弱等差数列 [1, 2] 和 [1, 2]。对于第四个元素 3,若我们将它添加到最后元素为 2 的序列中,则其公差必为 3 - 2 = 1。[1, 2] 和 [1, 2] 符合要求,故将 3 添加到这些序列后,答案增加 2。Similar to above, 与上一个元素类似,它也可以形成新的弱等差数列 [1, 3],[1, 3] 和 [2, 3]。其他元素以此类推,可参见下图。红色括号表示长度为 2 的弱等差数列,黑色括号表示等差数列。答案为黑色括号的数量。
class Solution {public int numberOfArithmeticSlices(int[] A) {int n = A.length;long ans = 0;Map<Integer, Integer>[] cnt = new Map[n];for (int i = 0; i < n; i++) {cnt[i] = new HashMap<>(i);for (int j = 0; j < i; j++) {long delta = (long)A[i] - (long)A[j];if (delta < Integer.MIN_VALUE || delta > Integer.MAX_VALUE) {continue;}int diff = (int)delta;int sum = cnt[j].getOrDefault(diff, 0);int origin = cnt[i].getOrDefault(diff, 0);cnt[i].put(diff, origin + sum + 1);ans += sum;}}return (int)ans;        }

在线java https://tool.lu/coderunner/

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class main {public static void main(String[] args) {int[] A = {1, 1, 2, 3, 4, 5};int n = A.length;long ans = 0;Map<Integer, Integer>[] cnt = new Map[n];for (int i = 0; i < n; i++) {cnt[i] = new HashMap<>(i);System.out.println(i+ "a");for (int j = 0; j < i; j++) {long delta = (long)A[i] - (long)A[j];if (delta < Integer.MIN_VALUE || delta > Integer.MAX_VALUE) {continue;}int diff = (int)delta;System.out.println(diff+"diff");int sum = cnt[j].getOrDefault(diff, 0);int origin = cnt[i].getOrDefault(diff, 0);System.out.println(origin+"origin");System.out.println(sum+"sum");cnt[i].put(diff, origin + sum + 1);ans += sum;}}System.out.println(ans);}
}

等差数列划分 II - 子序列相关推荐

  1. 等差数列划分 II - 子序列(动态规划)

    如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列. 例如,以下数列为等差数列: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9 以下数列不是 ...

  2. leetcode 446. Arithmetic Slices II - Subsequence | 446. 等差数列划分 II - 子序列(动态规划)

    题目 https://leetcode.com/problems/arithmetic-slices-ii-subsequence/ 题解 找等差子数列,详见注释. 一个月前做过,没通过,今天 dai ...

  3. 【数据结构与算法】之深入解析“等差数列划分II”的求解思路与算法示例

    一.题目要求 给你一个整数数组 nums ,返回 nums 中所有等差子序列的数目. 如果一个序列中至少有三个元素 ,并且任意两个相邻元素之差相同,则称该序列为等差序列. 例如,[1, 3, 5, 7 ...

  4. leetcode - 413. 等差数列划分

    413. 等差数列划分 -------------------------------------------- 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列. 例如 ...

  5. 等差数列java_Java实现 LeetCode 413 等差数列划分

    413. 等差数列划分 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列. 例如,以下数列为等差数列: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, - ...

  6. Leetcode-D26-动态规划(二刷)-413. 等差数列划分91. 解码方法

    昨天电脑在跑东西,卡的不行,用ipad写的题,没在csdn上写 413. 等差数列划分 1.有些思路了,写下看看. class Solution:def numberOfArithmeticSlice ...

  7. LeetCode--413. 等差数列划分

    413. 等差数列划分 思路:滑动窗口 如何理解每一次贡献值自增? 在三个数情况下 | | | Ans = 1 在四个数情况下 | | | | Ans = 1 + 2 在五个数情况下 | | | | ...

  8. Java实现 LeetCode 413 等差数列划分

    413. 等差数列划分 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列. 例如,以下数列为等差数列: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, - ...

  9. 看似动态规划,实则不需要——等差数列划分

    原题:等差数列划分 老规矩,先看看能否用递归解. 转换 假设现在的数列为[1,2,3,4,5,6],要怎么才能找出其子数列中所有的等差数列而无遗漏呢? 很容易想到,我们可以找出其所有子数列中以某数开头 ...

最新文章

  1. 和富友牵手与世界同步—高端体育时尚服装品牌的高标准伙伴
  2. 设计模式——10.单例模式
  3. jquery mobile自定义图标实现方法
  4. 服务器03系统怎么设置网站,Windows 2003系统路由服务的配置方法
  5. 如何设计APP版本号?
  6. Linux mv命令:移动文件或改名
  7. UVA11192 Group Reverse【水题】
  8. TS入门——01.数据类型
  9. Informatica的元数据和数据血缘关系
  10. Android手机avi转换为mp4手机,avi转mp4怎么进行 avi转mp4方法介绍【图解】
  11. 考研408(操作系统、计算机组成原理、数据结构、计算机网络)
  12. c语言数组统计选票,C语言实现选票统计
  13. xcode9 IphoneX 调试
  14. 【学习笔记】C++ GUI Qt4 第六章 6.4 滚动区域 和 6.5 停靠窗口和工具栏
  15. Token登录验证(附图)
  16. google map 地理编码API的两种方式
  17. 干货!MetaCorrection:解决无监督域适应的domain gap问题
  18. 【无人驾驶】“自主代客泊车”/自动泊车方案调研 2
  19. STM32芯片超低功耗设计思路
  20. 考研英语作文—遣词造句

热门文章

  1. 关于“算力”,这篇文章值得一看
  2. 多线程基础之设计模之Thread-Specific Storage模式
  3. [RS] 评价指标NDCG
  4. iOS 6发布的启示 —谈互联网产业链变化
  5. python 排课算法_list、dict和set的综合应用:排课系统(1)
  6. 阿里巴巴笔试题2020
  7. 〖产品思维训练白宝书 - 核心竞争力篇⑦〗- 产品经理核心竞争力解读之如何提升执行力
  8. 脚本开发教程分享:用按键精灵脚本查询本机 IP 地址
  9. 网络克隆自动修改计算机名ip,关于 Ghost 网络克隆后自动修改 IP 及计算机名的方法.doc...
  10. Keras embedding层的理解与使用