LeetCode3251 单调数组对数目
本题的子问题是下标 0 到 i 中的单调数组对的个数,且 arr1[i]=j,将其记作 f[i][j]。
class Solution {
public:
int countOfPairs(vector<int>& nums) {
const int mod=1e9+7;
int n=nums.size();
int m=nums[0];
for(int i=1;i<n;i++){
m=max(nums[i],m);
}
vector<vector<long long>> f(n,vector<long long>(m+1,0));
//f[i][j]表示下标0到i中单调数组对的个数,且arr1[i]=j
for(int i=0;i<=nums[0];i++) f[0][i]=1;
for(int i=1;i<n;i++){
for(int j=0;j<=nums[i];j++){
int sum=0;
for(int k=0;k<=j&&nums[i]-j<=nums[i-1]-k;k++)//arr1[i-1]<=arr1[i]且nums[i-1]-arr1[i-1]>=nums[i]-arr1[i]
sum=(sum+f[i-1][k])%mod;
f[i][j]=sum;
}
}
int res=0;
for(int i=0;i<=m;i++) res=(res+f[n-1][i])%mod;
return res;
}
};
时间复杂度:,其中n为数组nums长度,m为数组nums中的最大值。
空间复杂度:
前缀和优化:
class Solution {
public:
int countOfPairs(vector<int>& nums) {
const int mod=1e9+7;
int n=nums.size();
int m=nums[0];
for(int i=1;i<n;i++){
m=max(nums[i],m);
}
vector<vector<long long>> f(n,vector<long long>(m+1,0));
//f[i][j]表示下标0到i中单调数组对的个数,且arr1[i]=j
for(int i=0;i<=nums[0];i++) f[0][i]=1;
for(int i=1;i<n;i++){
/*
for(int j=0;j<=nums[i];j++){
int sum=0;
for(int k=0;k<=j&&nums[i]-j<=nums[i-1]-k;k++)//arr1[i-1]<=arr1[i]且nums[i-1]-arr1[i-1]>=nums[i]-arr1[i]
sum=(sum+f[i-1][k])%mod;
f[i][j]=sum;
}
*/
//前缀和优化
vector<long long> s(m+1);
s[0]=f[i-1][0];
for(int j=1;j<=nums[i];j++) s[j]=(s[j-1]+f[i-1][j])%mod;//求f[i]的前缀和
for(int j=0;j<=nums[i];j++){
if(j+nums[i-1]-nums[i]<0){//nums[i-1]-arr1[i-1]<nums[i]-arr1[i]
f[i][j]=0;
continue;
}
int k=min(j,j+nums[i-1]-nums[i]);
f[i][j]=s[k];
}
}
int res=0;
for(int i=0;i<=m;i++) res=(res+f[n-1][i])%mod;
return res;
}
};
时间复杂度:,其中n为数组nums长度,m为数组nums中的最大值。
空间复杂度: