leetcode
leetcode 2251 ~ 2300
统计上升四元组

统计上升四元组

难度:

标签:

题目描述

Given a 0-indexed integer array nums of size n containing all numbers from 1 to n, return the number of increasing quadruplets.

A quadruplet (i, j, k, l) is increasing if:

  • 0 <= i < j < k < l < n, and
  • nums[i] < nums[k] < nums[j] < nums[l].

 

Example 1:

Input: nums = [1,3,2,4,5]
Output: 2
Explanation: 
- When i = 0, j = 1, k = 2, and l = 3, nums[i] < nums[k] < nums[j] < nums[l].
- When i = 0, j = 1, k = 2, and l = 4, nums[i] < nums[k] < nums[j] < nums[l]. 
There are no other quadruplets, so we return 2.

Example 2:

Input: nums = [1,2,3,4]
Output: 0
Explanation: There exists only one quadruplet with i = 0, j = 1, k = 2, l = 3, but since nums[j] < nums[k], we return 0.

 

Constraints:

  • 4 <= nums.length <= 4000
  • 1 <= nums[i] <= nums.length
  • All the integers of nums are unique. nums is a permutation.

代码结果

运行时间: 68 ms, 内存: 17.7 MB


/*
 * 思路:
 * 使用Java Stream API来处理数组中的每个元素。
 * 虽然Stream API不能直接处理嵌套循环,但我们可以通过flatMap等方法展开流,
 * 然后用过滤器条件来找到符合条件的四元组。
 */
import java.util.stream.IntStream;

public class Solution {
    public int countIncreasingQuadruplets(int[] nums) {
        int n = nums.length;
        return (int) IntStream.range(0, n)
            .boxed()
            .flatMap(i -> IntStream.range(i + 1, n)
                .boxed()
                .flatMap(j -> IntStream.range(j + 1, n)
                    .boxed()
                    .flatMap(k -> IntStream.range(k + 1, n)
                        .filter(l -> nums[i] < nums[k] && nums[k] < nums[j] && nums[j] < nums[l])
                        .boxed()))
            ).count();
    }
}

解释

方法:

题解采用了一种高效的方法来计算数组中的特定四元组的数量。整体思路是利用一个计数数组 cnt 来存储特定条件下的计数。对于每个位置 l,我们遍历所有 j(j < l),检查 a[j] 是否小于 a[l]。如果条件满足,则将 cnt[j] 的值累加到结果 ans 上,并且将 x(x 记录从 0 到当前 j 的满足条件 a[i] < a[k] < a[j] 的数量)累加 1。如果条件不满足,则将 x 的值累加到 cnt[j] 上,这样在未来的遍历中,当遇到适合的 a[l] 时,可以直接利用 cnt[j] 来更新答案。这种方法巧妙地避免了四重循环,通过三重循环和巧妙的统计优化了计算。

时间复杂度:

O(n^2)

空间复杂度:

O(n)

代码细节讲解

🦆
题解中提到的计数数组 cnt[j] 存储的是什么具体的信息?
在题解中,计数数组 cnt[j] 存储的是对于每个固定的 j,满足 i < j < k < l 和 nums[i] < nums[k] < nums[j] < nums[l] 条件的 i 和 k 的组合数量。这样的设置是为了在遍历到 l 时,能够直接利用 cnt[j] 来统计满足条件的四元组数量,从而避免重复的四重遍历。
🦆
在题解中,为什么要在 a[j] < a[l] 的条件下将 x 累加到 cnt[j] 上?这样做的目的是什么?
在 a[j] < a[l] 的条件下将 x 累加到 cnt[j] 上,是因为 x 记录的是从位置 0 到当前 j 之间,满足 nums[i] < nums[k] < nums[j] 的二元组 (i, k) 的数量。当我们确认 nums[j] < nums[l] 时,意味着这些二元组 (i, k) 可以与当前的 j 和 l 形成满足条件的四元组。因此,我们将这个数量累加到 cnt[j] 中,以便后续可以直接使用,这样做主要是为了优化计算效率,避免重复计算已经统计过的组合数量。
🦆
题解采用的方法是否能够确保每个四元组都是唯一的,即没有重复计算?如果可以,是如何避免重复的?
题解采用的方法可以确保每个四元组都是唯一的,没有重复计算。这是因为在遍历过程中,每个元素的位置 i, j, k, l 都严格按照 i < j < k < l 的顺序来选取,且 nums 的条件也严格按照 nums[i] < nums[k] < nums[j] < nums[l] 来检查。通过这种方式,每个四元组的组合都是唯一确定的,不存在位置或值的重复,从而确保了四元组的唯一性。

相关问题