[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 ...
随机推荐
- TFS工作项数据统计及相关数据库结构分析
今天为客户的质量管理部门人员提供TFS咨询过程中,客户的质量管理专家基于TFS提出了一个比较棘手的数据统计需求.需求是这样,客户的数十个软件项目通过质量管理部按照年度版本计划进行软件产品系统的发布,因 ...
- Java进击C#——语法之多线程
本章简言 上一章中笔者对C#一些独有的语法点进行讲解,相信也可以看C#的一些神奇之处.那么本章主要是放在多线程这方面的知识.不管是C#还是JAVA在开发过程或多或少都会用到关于多线程的编程.当然笔者不 ...
- 3.EF 6.0 Code-First实现增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-entity-framework-5-0-code- ...
- Yii 2.x RESTful 应用 - 类图
配置url管理器配置请求数据解析器配置用户控制器 ['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']
- CentOS系统配置 iptables防火墙
阿里云CentOS系统配置iptables防火墙 虽说阿里云推出了云盾服务,但是自己再加一层防火墙总归是更安全些,下面是我在阿里云vps上配置防火墙的过程,目前只配置INPUT.OUTPUT和FO ...
- stream_set_timeout (fread 造成了php程序timeout)
最近在执行fread时候,php出现了 "Fatal error: Maximum execution time of 30 seconds " fread() :从文件指针 ha ...
- 4.5 .net core下直接执行SQL语句并生成DataTable
.net core可以执行SQL语句,但是只能生成强类型的返回结果.例如var blogs = context.Blogs.FromSql("SELECT * FROM dbo.Blogs& ...
- String 中去掉空格
JAVA中去掉空格 1. String.trim() trim()是去掉首尾空格 2.str.replace(" ", ""); 去掉所有空格,包括首尾.中间 ...
- sed的应用
h3 { color: rgb(255, 255, 255); background-color: rgb(30,144,255); padding: 3px; margin: 10px 0px } ...
- FineReport实现EXCEL数据导入自由报表
在制作填报报表的时候,对于空白填报表,常常导出为Excel,派发给各部门人员填写后上交.如何能避免手动输入,直接将Excel中的数据导入到填报表中提交入库呢? 这里以一个简单的员工信息填报示例进行介绍 ...