2552. 统计上升四元组
题目描述
给你一个长度为n
下标从 0
开始的整数数组 nums
,它包含1
到n
的所有数字,请你返回上升四元组的数目。
如果一个四元组 (i, j, k, l)
满足以下条件,我们称它是上升的:
0 <= i < j < k < l < n
且nums[i] < nums[k] < nums[j] < nums[l]
。
示例 1:
输入:nums = [1,3,2,4,5]
输出:2
解释:
- 当 i = 0 ,j = 1 ,k = 2 且 l = 3 时,有 nums[i] < nums[k] < nums[j] < nums[l] 。
- 当 i = 0 ,j = 1 ,k = 2 且 l = 4 时,有 nums[i] < nums[k] < nums[j] < nums[l] 。
没有其他的四元组,所以我们返回 2 。
示例 2:
输入:nums = [1,2,3,4]
输出:0
解释:没有四元组,所以我们返回 0 。
提示:
4 <= nums.length <= 4000
1 <= nums[i] <= nums.length
nums 中所有数字 互不相同 ,nums 是一个排列。
解题思路
我们可以枚举四元组中的 j
和 k
,那么问题转化为,对于当前的 j
和 k
:
统计有多少个 l
满足 l
>k
且 nums[l]
>nums[j]
,记为cnt1
;
统计有多少个 i
满足 i
<j
且 nums[i]
<nums[k]
,记为cnt2
;
所以,对于每一组 j
和 k
,满足条件的组合数目为cnt1*cnt2
,将所有j
和 k
组合数目相加,就是答案。
那么我们可以用动态规划解决这个问题。
使用二维数组 f
来记录 j
和 k
组合的情况,f[j][k]
表示 有多少个l
满足满足 l
>k
且 nums[l]
>nums[j]
。
初始化 f[j][n-1]
为 0
,表示对于末尾元素为k
的情况下,没有满足条件的l
。注意1<=j<n-2
。
从后往前填充行f[j]
,如果nums[k]>nums[j]
,则f[j][k-1]
=f[j][k]+1
。
此时,对于每个j
和 k
,我们都可以计算出有多少个 l
满足 l
>k
且 nums[l]
>nums[j]
,即cnt1=f[j][k]
。
对于每个j
和 k
,我们已经通过二维数组 f
,记录了cnt1
的取值,接下来,我们只需要记录cnt2
的取值即可。
对于每个j
和 k
,我们可以确定k
,,之后从前往后遍历数组。
初始化cnt2=0
,如果
nums[j]<nums[k]
,则cnt2+=1
,表示当前有多少个i
满足nums[i]
<nums[k]
。nums[j]>nums[k]
,则当前j
和k
满足条件,我们将cnt2*cnt1
即cnt2*f[j][k]
加入答案。
最后,返回答案即可。
复杂度分析:
- 时间复杂度: O ( n 2 ) O(n^2) O(n2),其中 n n n 是数组的长度。
- 空间复杂度: O ( n 2 ) O(n^2) O(n2),其中 n n n 是数组的长度。
代码实现
Python实现:
python
class Solution(object):
def countQuadruplets(self, nums):
n=len(nums)
f=[[0]*n for i in range(n)]
ans=0
for j in range(1,n-2):
cnt=0
for k in range(n-1,j,-1):
f[j][k]=cnt
if nums[k]>nums[j]:
cnt+=1
for k in range(2,n-1):
cnt=0
for j in range(0,k):
if(nums[j]>nums[k]):
ans+=cnt*f[j][k]
else:
cnt+=1
return ans
C++实现:
cpp
class Solution {
public:
long long countQuadruplets(vector<int>& nums) {
int n=nums.size();
vector<vector<int>> f(n,vector<int>(n,0));
long long res=0;
for(int j=1;j<n-2;j++){
int cnt=0;
for(int k=n-1;k>j;k--){
f[j][k]=cnt;
if(nums[k]>nums[j]){
cnt++;
}
}
}
for(int k=2;k<n-1;k++){
int cnt=0;
for(int j=0;j<k;j++){
if(nums[j]<nums[k]){
cnt++;
continue;
}else{
res+=cnt*f[j][k];
}
}
}
return res;
}
};
Go实现:
go
func countQuadruplets(nums []int) int64 {
n := len(nums)
f := make([][]int, n)
for i := range f {
f[i] = make([]int, n)
}
for j := 1; j < n-2; j++ {
cnt := 0
for k := n-1; k >j; k-- {
f[j][k] = cnt
if nums[j] < nums[k] {
cnt++
}
}
}
ans := 0
for k := 2; k < n-1; k++ {
cnt := 0
for j := 0; j <k; j++ {
if nums[j] < nums[k] {
cnt++
continue
}else{
ans+=cnt*f[j][k]
}
}
}
return int64(ans)
}