等差数列划分II 子序列

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

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

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]

Dynamic Programming [Accepted]

Intuition

To determine an arithmetic sequence, we need at least two parameters: the first (or last) element of the sequence, and the common difference.

Algorithm

Starting from this point, we can easily figure out that one state representation that may work:

f[i][d] denotes the number of arithmetic subsequences that ends with A[i] and its common difference is d.

Let's try to find the state transitions based on the representation above. Assume we want to append a new element A[i] to existing arithmetic subsequences to form new subsequences. We can append A[i] to an existing arithmetic subsequence, only if the difference between the sequence's last element and A[i] is equal to the sequence's common difference.

Thus, we can define the state transitions for the element A[i] intuitively :

for all j < i, f[i][A[i] - A[j]] += f[j][A[i] - A[j]].

This demonstrates the appending process above to form new arithmetic subsequences.

But here comes the problem. Initially all f[i][d] are set to be 0, but how can we form a new arithmetic subsequence if there are no existing subsequences before?

In the original definition of arithmetic subsequences, the length of the subsequence must be at least 3. This makes it hard to form new subsequences if only two indices i and j are given. How about taking the subsequences of length 2 into account?

We can define weak arithmetic subsequences as follows:

Weak arithmetic subsequences are subsequences that consist of at least two elements and if the difference between any two consecutive elements is the same.

There are two properties of weak arithmetic subsequences that are very useful:

  • For any pair i, j (i != j), A[i] and A[j] can always form a weak arithmetic subsequence.
  • If we can append a new element to a weak arithmetic subsequence and keep it arithmetic, then the new subsequence must be an arithmetic subsequence.

The second property is quite trival, because the only difference between arithmetic subsequences and weak arithmetic subsequences is their length.

Thus we can change the state representations accordingly:

f[i][d] denotes the number of weak arithmetic subsequences that ends with A[i] and its common difference is d.

Now the state transitions are quite straightforward:

for all j < i, f[i][A[i] - A[j]] += (f[j][A[i] - A[j]] + 1).

The 1 appears here because of the property one, we can form a new weak arithmetic subsequence for the pair (i, j).

Now the number of all weak arithmetic subsequences is the sum of all f[i][d]. But how can we get the number of arithmetic subsequences that are not weak?

There are two ways:

  • First, we can count the number of pure weak arithmetic subsequences directly. The pure weak arithmetic subsequences are the arithmetic subsequences of length 2, so the number of pure weak arithmetic subsequences should be equal to the number of pairs (i, j), which is (n2)=n∗(n−1)2.\binom{n}{2} = \frac{n * (n - 1)}{2}.(2n​)=2n∗(n−1)​.
  • Second, for the summation f[i][A[i] - A[j]] += (f[j][A[i] - A[j]] + 1), f[j][A[i] - A[j]] is the number of existing weak arithmetic subsequences, while 1 is the new subsequence built with A[i] and A[j]. Based on property two, when we are appending new elements to existing weak arithmetic subsequences, we are forming arithmetic subsequences. So the first part, f[j][A[i] - A[j]] is the number of new formed arithmetic subsequences, and can be added to the answer.

We can use the following example to illustrate the process:

[1, 1, 2, 3, 4, 5]

We need to count the answer for the above sequence.

  • For the first element 1, there is no element in front of it, the answer remains 0.
  • For the second element 1, the element itself with the previous 1 can form a pure weak arithmetic subsequence with common difference 0 : [1, 1].
  • For the third element 2, it cannot be appended to the only weak arithmetic subsequence [1, 1], so the answer remains 0. Similar to the second element, it can form new weak arithmetic subsequences [1, 2] and [1, 2].
  • For the forth element 3, if we append it to some arithmetic subsequences ending with 2, these subsequences must have a common difference of 3 - 2 = 1. Indeed there are two: [1, 2] and [1, 2]. So we can append 3 to the end of these subsequences, and the answer is added by 2. Similar to above, it can form new weak arithmetic subsequences [1, 3], [1, 3] and [2, 3].
  • The other elements are the same, we can view the process in the figure below. The red bracket indicates the weak arithmetic subsequence of length 2, and the black bracket indicates the arithmetic subsequence. The answer should be the total number of black brackets.

 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;
}
}

Leetcode 446.等差数列划分II 子序列的更多相关文章

  1. Java实现 LeetCode 446 等差数列划分 II - 子序列

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

  2. [Swift]LeetCode446. 等差数列划分 II - 子序列 | Arithmetic Slices II - Subsequence

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  3. Leetcode 413.等差数列划分

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

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

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

  5. Leetcode——413. 等差数列划分

    题目描绘:题目链接 题目中需要求解一个数组中等差数组的个数,这个问题可以利用动态规划的思路来分析. 三步骤: 1:问题归纳.题目需要求解等差数列的和,我们可以用一个数组保存前i个元素可以构成的等差数列 ...

  6. LeetCode 446. Arithmetic Slices II - Subsequence

    原题链接在这里:https://leetcode.com/problems/arithmetic-slices-ii-subsequence/ 题目: A sequence of numbers is ...

  7. 第六周 Leetcode 446. Arithmetic Slices II - Subsequence (HARD)

    Leetcode443 题意:给一个长度1000内的整数数列,求有多少个等差的子数列. 如 [2,4,6,8,10]有7个等差子数列. 想了一个O(n^2logn)的DP算法 DP[i][j]为 对于 ...

  8. Leetcode之动态规划(DP)专题-413. 等差数列划分(Arithmetic Slices)

    Leetcode之动态规划(DP)专题-413. 等差数列划分(Arithmetic Slices) 如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列. 例如,以下数列为 ...

  9. LeetCode Single Number I / II / III

    [1]LeetCode 136 Single Number 题意:奇数个数,其中除了一个数只出现一次外,其他数都是成对出现,比如1,2,2,3,3...,求出该单个数. 解法:容易想到异或的性质,两个 ...

随机推荐

  1. ESP8266串口WiFi扩展板详解

    产品简介 ESP8266串口WiFi扩展板是深圳四博智联科技有限公司开发的一款基于乐鑫ESP8266的超低功耗的UART-WiFi模块,兼容Arduino UNO.Mega等标准主板,可以方便地进行二 ...

  2. Selenium3+webdriver学习笔记2(常用元素定位方式,定位单个元素共8种,总共有23种)

    #!/usr/bin/env python# -*- coding:utf-8 -*- from selenium import webdriver import time,os # about:ad ...

  3. 【TensorFlow入门完全指南】模型篇·最近邻模型

    最近邻模型,更为常见的是k-最近邻模型,是一种常见的机器学习模型,原理如下: KNN算法的前提是存在一个样本的数据集,每一个样本都有自己的标签,表明自己的类型.现在有一个新的未知的数据,需要判断它的类 ...

  4. Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash

    E. The Classic Problem http://codeforces.com/problemset/problem/464/E 题意:给你一张无向带权图,求S-T的最短路,并输出路径.边权 ...

  5. JavaScript对象属性

    JavaScript对象的属性有两类:数据属性和访问器属性 数据属性 数据属性有四个特性,分别为: [[value]]属性的值 [[writeable]]属性是否可以修改 [[enumerable]] ...

  6. 巧用代理设计模式(Proxy Design Pattern)改善前端图片加载体验

    这篇文章介绍一种使用代理设计模式(Proxy Design Pattern)的方法来改善您的前端应用里图片加载的体验. 假设我们的应用里需要显示一张尺寸很大的图片,位于远端服务器.我们用一些前端框架的 ...

  7. ABAP vs Java, 蛙泳 vs 自由泳

    去年7月定下的一年之内学会自由泳的目标终于实现了,特来还愿. ABAP和Java, 蛙泳和自由泳.前面的组合是Jerry用来挣钱养家的技术,后者是Jerry花了大量业余时间和金钱苦练的技能.或许有的朋 ...

  8. OpenGL小试牛刀第一季

    效果截图:代码展示:using System;using System.Collections.Generic;using System.ComponentModel;using System.Dat ...

  9. Linux curl命令中,HTTP 302处理

    在Linux中使用curl命令时,偶尔会遇到一些URL跳转到新的URL,即HTTP中的3XX(redirection,重定向 ). $curl -s -I $URL > log 这时在返回的报文 ...

  10. React组件自适应窗口宽高

    很多时候我们需要组件能够根据窗口变化改变宽高,有时候可以使用css,有时候需要随数据调整则使用js计算. 比如说,当我们在页面中放置一个iframe时,我们希望它的宽高随着其父元素or窗口的变化而变化 ...