[LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列
A sequence of numbers is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.
For example, these are arithmetic sequences:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
The following sequence is not arithmetic.
1, 1, 2, 5, 7
A zero-indexed array A consisting of N numbers is given. A subsequence slice of that array is any sequence of integers (P0, P1, ..., Pk) such that 0 ≤ P0 < P1 < ... < Pk < N.
A subsequence slice (P0, P1, ..., Pk) of array A is called arithmetic if the sequence A[P0], A[P1], ..., A[Pk-1], A[Pk] is arithmetic. In particular, this means that k ≥ 2.
The function should return the number of arithmetic subsequence slices in the array A.
The input contains N integers. Every integer is in the range of -231 and 231-1 and 0 ≤ N ≤ 1000. The output is guaranteed to be less than 231-1.
Example:
Input: [2, 4, 6, 8, 10] Output: 7 Explanation:
All arithmetic subsequence slices are:
[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]
这道题是之前那道Arithmetic Slices的延伸,那道题比较简单是因为要求等差数列是连续的,而这道题让我们求是等差数列的子序列,可以跳过某些数字,不一定非得连续,那么难度就加大了,但还是需要用动态规划Dynamic Progrmming来做。知道用DP来做是一回事,真正能做出来又是另一回事。刷题的最终目的不是背题,而是训练思维方式,如何从完全没思路,变为好像有点思路,慢慢推理演变找出正确解,就像顺着藏宝图的丝丝线索最终发现了宝藏一样,是无比的令人激动和富有成就感的过程。死记硬背的话,只要题目稍稍变形一下就完蛋。这就是为啥博主喜欢看fun4LeetCode大神的帖子,虽然看范佛力扣大神的帖子像读论文,但是有推理过程,看完让人神清气爽,茶饭不思,燃鹅遇到同类型的还是不会,还是要再看。好,博主皮一下就行了,就不皮几万了,下面来顺着大神的帖子来讲吧。
好,既然决定要用DP了,那么首先就要确定dp数组的定义了,刚开始我们可能会考虑使用个一维的dp数组,然后dp[i]定义为范围为[0, i]的子数组中等差数列的个数。定义的很简单,OK,但是基于这种定义的状态转移方程却十分的难想。我们想对于(0, i)之间的任意位置j,如何让 dp[i] 和 dp[j] 产生关联呢?是不是只有 A[i] 和 A[j] 的差值diff,跟A[j]之前等差数列的差值相同,才会有关联,所以差值diff是一个很重要的隐藏信息Hidden Information,我们必须要在dp的定义中考虑进去。所以一维dp数组是罩不住的,必须升维,但是用二维dp数组的话,差值diff那一维的范围又是个问题,数字的范围是整型数,所以差值的范围也很大,为了节省空间,我们建立一个一维数组dp,数组里的元素不是数字,而是放一个HashMap,建立等差数列的差值和当前位置之前差值相同的数字个数之间的映射。我们遍历数组中的所有数字,对于当前遍历到的数字,又从开头遍历到当前数字,计算两个数字之差diff,如果越界了不做任何处理,如果没越界,我们让dp[i]中diff的差值映射自增1,因为此时A[i]前面有相差为diff的A[j],所以映射值要加1。然后我们看dp[j]中是否有diff的映射,如果有的话,说明此时相差为diff的数字至少有三个了,已经能构成题目要求的等差数列了,将dp[j][diff]加入结果res中,然后再更新dp[i][diff],这样等遍历完数组,res即为所求。
我们用题目中给的例子数组 [2,4,6,8,10] 来看,因为2之前没有数字了,所以我们从4开始,遍历前面的数字,是2,二者差值为2,那么在dp[1]的HashMap就可以建立 2->1 的映射,表示4之前有1个差值为2的数字,即数字2。那么现在i=2指向6了,遍历前面的数字,第一个数是2,二者相差4,那么在dp[2]的HashMap就可以建立 4->1 的映射,第二个数是4,二者相差2,那么先在dp[2]的HashMap建立 2->1 的映射,由于dp[1]的HashMap中也有差值为2的映射,2->1,那么说明此时至少有三个数字差值相同,即这里的 [2 4 6],我们将dp[1]中的映射值加入结果res中,然后当前dp[2]中的映射值加上dp[1]中的映射值。这应该不难理解,比如当i=3指向数字8时,j=2指向数字6,那么二者差值为2,此时先在dp[3]建立 2->1 的映射,由于dp[2]中有 2->2 的映射,那么加上数字8其实新增了两个等差数列 [2,4,6,8] 和 [4,6,8],所以结果res加上的值就是 dp[j][diff],即2,并且 dp[i][diff] 也需要加上这个值,才能使得 dp[3] 中的映射变为 2->3 ,后面数字10的处理情况也相同,这里就不多赘述了,最终的各个位置的映射关系如下所示:
2 4 6 8 10
2->1 4->1 6->1 8->1
2-> 4->1 6->1
2-> 4->
2->
最终累计出来的结果是跟上面红色的数字相关,分别对应着如下的等差数列:
2->2:[2,4,6]
2->3:[2,4,6,8] [4,6,8]
4->2:[2,6,10]
2->4:[2,4,6,8,10] [4,6,8,10] [6,8,10]
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& A) {
int res = , n = A.size();
vector<unordered_map<int, int>> dp(n);
for (int i = ; i < n; ++i) {
for (int j = ; j < i; ++j) {
long delta = (long)A[i] - A[j];
if (delta > INT_MAX || delta < INT_MIN) continue;
int diff = (int)delta;
++dp[i][diff];
if (dp[j].count(diff)) {
res += dp[j][diff];
dp[i][diff] += dp[j][diff];
}
}
}
return res;
}
};
类似题目:
参考资料:
https://leetcode.com/problems/arithmetic-slices-ii-subsequence/solution/
https://leetcode.com/problems/arithmetic-slices-ii-subsequence/discuss/92837/C++_DP_Accepted
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列的更多相关文章
- 446 Arithmetic Slices II - Subsequence 算数切片之二 - 子序列
详见:https://leetcode.com/problems/arithmetic-slices-ii-subsequence/description/ C++: class Solution { ...
- Leetcode: Arithmetic Slices II - Subsequence
A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...
- Arithmetic Slices II - Subsequence LT446
446. Arithmetic Slices II - Subsequence Hard A sequence of numbers is called arithmetic if it consis ...
- LeetCode 446. Arithmetic Slices II - Subsequence
原题链接在这里:https://leetcode.com/problems/arithmetic-slices-ii-subsequence/ 题目: A sequence of numbers is ...
- 第六周 Leetcode 446. Arithmetic Slices II - Subsequence (HARD)
Leetcode443 题意:给一个长度1000内的整数数列,求有多少个等差的子数列. 如 [2,4,6,8,10]有7个等差子数列. 想了一个O(n^2logn)的DP算法 DP[i][j]为 对于 ...
- [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 ...
- LeetCode446. Arithmetic Slices II - Subsequence
A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...
- 446. Arithmetic Slices II - Subsequence
A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...
- [LeetCode] Arithmetic Slices 算数切片
A sequence of number is called arithmetic if it consists of at least three elements and if the diffe ...
随机推荐
- 浅谈css的栅格布局
栅格布局想必大家都很了解,我们做页面开发的时候,往往对页面板式的要求很高,如何对各个区域的内容排版,并使之对齐是我们的一大难题.而栅格系统就是我们排版的利器,他支持自动对齐.自动计算边距.流式布局等优 ...
- Guass列选主元消去法和三角分解法
最近数值计算学了Guass列主消元法和三角分解法解线性方程组,具体原理如下: 1.Guass列选主元消去法对于AX =B 1).消元过程:将(A|B)进行变换为,其中是上三角矩阵.即: k从1到n-1 ...
- WPF binding 参考
Introduction This is an article on WPF Binding Cheat Sheet. Some of the Binding won't work for Silve ...
- spring笔记6 spring IOC的中级知识
1,spring ioc的整体流程,xml配置 spring ioc初始化的流程结合上图 步骤编号 完成的工作 1 spring容器读取配置文件,解析称注册表 2 根据注册表,找到相应的bean实现类 ...
- c3p0连接数据库的3种方式
c3p0连接数据库的3种方式,这里以mysql为例 1. 直接用set方法设置参数, 基本方法 ComboPooledDataSource dataSource = new ComboPooledDa ...
- jdk jre jvm 三者之间关系
JDK JDK是java开发工具包,是Sun公司针对Java开发员的产品. JDK 中包含JRE,在JDK安装的目录下有一个叫jre的目录,里面有两个文件夹,bin/和lib,其中bin就是j ...
- 纯css3 3D图片立方体旋转动画特效
纯css3 3D立方体模块,鼠标触碰,模块炸开,大立方体中套小立方体 效果展示 手机扫描二维码体验效果: 效果图如下: 源码下载:http://hovertree.com/h/bjaf/0qmul8g ...
- 浅谈Hybrid技术的设计与实现第二弹
前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术的设计与实现第三弹——落地篇 接上文:浅谈Hybrid技术的设计与实现(阅读本文前,建议阅读这个先) ...
- 玩儿转物联网IoT - 在Beagle Bone Black上运行node.js 程序
物联网(IoT)技术方兴未艾,智能手环,智能血压计,智能眼镜甚至智能鞋垫都开始进入我们的生活,各种智能设备层出不穷,世界已经到了一个"人有多大胆,地有多大产"的时代,不玩儿点物联网 ...
- iOS - GitHub干货分享(APP引导页的高度集成 - DHGuidePageHUD - ①)
好长时间没更新博客, 是时候来一波干货分享了;APP引导页话不多说每一个APP都会用到,分量不重但是不可缺少,不论是APP的首次安装还是版本的更新,首先展现给用户眼前的也就只有它了吧,当然这里讲的不是 ...