题目:
相关企业
给你一个长度为 n 下标从 0 开始的整数数组 nums ,它包含 1 到 n 的所有数字,请你返回上升四元组的数目。
如果一个四元组 (i, j, k, l) 满足以下条件,我们称它是上升的:
0 <= i < j < k < l < n且nums[i] < nums[k] < nums[j] < nums[l]。
算法:
方法一:枚举
技巧:我们考虑对符合条件的j,k进行枚举:
- great[k][nums[j]]表示k右侧大于nums[j]的元素个数。
- less[j][nums[k]]表示j左侧小于nums[k]的元素个数。
针对每一个符合条件的(j,k),上升四元组的数目为:less[j][nums[k]] * great[k][nums[j]]。
- 维护great数组,从右往左遍历得到元素值x,那么对于所有的great[k][0~x - 1]都 都要+1
- 维护less数组,从左往右遍历得到元素x,那么对于所有的less[j][x + 1 ~ n]都要+1
func countQuadruplets(nums []int) int64 {
n := len(nums)
great := make([][]int, n)
great[n - 1] = make([]int, n + 1)
for k := n - 2; k >= 1; k -- {
// k = 6,great[k][3]=3
// 那么k = 5时,great[k][3]至少也是3,less同理。
great[k] = append([]int{} ,great[k + 1]...)
for x := nums[k + 1] - 1; x >= 0; x -- {
great[k][x] ++
}
}
less := make([]int, n + 1)
ans := int64(0)
for j := 1; j <= n - 2; j ++ {
for x := nums[j - 1] + 1; x <= n; x ++ {
less[x] ++
}
for k := j + 1; k < n - 1; k ++ {
if nums[j] > nums[k] {
ans = ans + int64(less[nums[k]] * great[k][nums[j]])
}
}
}
return ans
}
方法二:前缀和+后缀和
- great[i][x]表示 i <= index 且x <= value的nums元素个数
- less[i][x]表示 index <= i且value <= x 的nums元素个数
结果为:
var great, less [4003][4003]int
func countQuadruplets(nums []int) int64 {
n := len(nums)
// 对great,less数组初始化,否则上次的执行结果会影响下一次
for i := 0; i <= n + 1; i ++ {
for j := 0; j <= n + 1; j ++ {
great[i][j] = 0
less[i][j] = 0
}
}
// great[i][x]表示 i <= index 且x <= value的nums元素个数
// less[i][x]表示 index <= i且value <= x 的nums元素个数
// great,less相对nums的index有+1的偏移量
// great, less = [4003][4003]int{}, [4003][4003]int{}
for i := 1; i <= n; i ++ {
great[i][nums[i - 1]] = 1
less[i][nums[i - 1]] = 1
}
// 初始化less数组,前缀和
for i := 1; i <= n; i ++ {
for j := 1; j <= n; j ++ {
less[i][j] = less[i][j] + less[i][j - 1]
}
}
for i := 1; i <= n; i ++ {
for j := 1; j <= n; j ++ {
less[i][j] = less[i][j] + less[i - 1][j]
}
}
// 初始化great数组,后缀和
for i := n; i > 0; i -- {
for j := n; j > 0; j -- {
great[i][j] = great[i][j] + great[i][j + 1]
}
}
for i := n; i > 0; i -- {
for j := n; j > 0; j -- {
great[i][j] = great[i][j] + great[i + 1][j]
}
}
// 计算结果
ans := int64(0)
// j:[1,n-2],k[2,n-1];
// j,k都有+1的偏移量
for j := 1; j <= n ; j ++ {
for k := j + 1; k <= n; k ++ {
if nums[j - 1] > nums[k - 1] {
// fmt.Println(j-1, k-1,less[j - 1][nums[k - 1] - 1], great[k + 1][nums[j - 1] + 1])
ans = ans + int64(less[j - 1][nums[k - 1] - 1] * great[k + 1][nums[j - 1] + 1])
}
}
}
return ans
}