1. 前言
区间类型问题,指求一个数列中某一段区间的值,包括求和、最值等简单或复杂问题。此类问题也适用于动态规划思想。
如前缀和
就是极简单的区间问题。如有如下数组:
int nums[]={3,1,7,9,12,78,32,5,10,11,21,32,45,22}
现给定区间信息[3,6]
,求区间内所有数字相加结果。即求如下图位置数字之和。
Tips: 区间至少包括
2
个属性,起始端和结束端,求和范围包含左端和右端数字。
直接的解法:
- 累加数组中
0~6
区间的值s1
。 - 累加数组中
0~2
区间的值s2
。 - 将
s1
中的值减去s2
中的值。得到最终结果。
如果对任意区间的求解要求较频繁,会存在大量的重复计算。如分别求区间[2,5]
和[1,5]
之和时,分析可知区间[1,5]
结果等于区间[2,5]
的结果加上nums[1]
的值,或者说区间[2,5]
的值等于[1,5]
的值减nums[1]
。简而言之,只需要求出一个如上两个区间中一个区间的值,另一个区间的值就可得到。
为了减少重复计算,可使用区间缓存理念记录0~
至任意位置的和。
如上的问题便是简单的区间类型问题,解决此类问题的方案称为简单区间类型动态规划。dp
数组也可称为前缀和数组。
编码实现:
#include <iostream>
using namespace std;
int main() {
int nums[]= {3,1,7,9,12,78,32,5,10,11,21,32,45,22};
int dp[100];
int size=sizeof(nums)/sizeof(int);
for(int i=0; i<size; i++) {
if(i==0){
//base case
dp[i]=nums[i];
}else{
dp[i]=dp[i-1]+nums[i];
}
}
//输出dp信息
for(int i=0; i<size; i++) {
cout<<dp[i]<<"\t";
}
return 0;
}
有了前缀和数组,计算任意区间数字和的公式为:
//