LeetCode 题解工作台

统计上升四元组

给你一个长度为 n 下标从 0 开始的整数数组 nums ,它包含 1 到 n 的所有数字,请你返回上升四元组的数目。 如果一个四元组 (i, j, k, l) 满足以下条件,我们称它是上升的: 0 且 nums[i] 。 示例 1: 输入: nums = [1,3,2,4,5] 输出: 2 解释:…

category

5

题型

code_blocks

4

代码语言

hub

3

相关题

当前训练重点

困难 · 状态·转移·动态规划

bolt

答案摘要

我们可以枚举四元组中的 和 ,那么问题转化为,对于当前的 和 : - 统计有多少个 满足 $l \gt k$ 且 $nums[l] \gt nums[j]$;

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个长度为 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
解释:只存在一个四元组 i = 0 ,j = 1 ,k = 2 ,l = 3 ,但是 nums[j] < nums[k] ,所以我们返回 0 。

 

提示:

  • 4 <= nums.length <= 4000
  • 1 <= nums[i] <= nums.length
  • nums 中所有数字 互不相同 ,nums 是一个排列。
lightbulb

解题思路

方法一:枚举 + 预处理

我们可以枚举四元组中的 jjkk,那么问题转化为,对于当前的 jjkk

  • 统计有多少个 ll 满足 l>kl \gt knums[l]>nums[j]nums[l] \gt nums[j]
  • 统计有多少个 ii 满足 i<ji \lt jnums[i]<nums[k]nums[i] \lt nums[k]

我们可以使用两个二维数组 ffgg 分别记录这两个信息。其中 f[j][k]f[j][k] 表示有多少个 ll 满足 l>kl \gt knums[l]>nums[j]nums[l] \gt nums[j],而 g[j][k]g[j][k] 表示有多少个 ii 满足 i<ji \lt jnums[i]<nums[k]nums[i] \lt nums[k]

那么答案就是所有的 f[j][k]×g[j][k]f[j][k] \times g[j][k] 的和。

时间复杂度为 O(n2)O(n^2),空间复杂度为 O(n2)O(n^2)。其中 nn 是数组的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
    def countQuadruplets(self, nums: List[int]) -> int:
        n = len(nums)
        f = [[0] * n for _ in range(n)]
        g = [[0] * n for _ in range(n)]
        for j in range(1, n - 2):
            cnt = sum(nums[l] > nums[j] for l in range(j + 1, n))
            for k in range(j + 1, n - 1):
                if nums[j] > nums[k]:
                    f[j][k] = cnt
                else:
                    cnt -= 1
        for k in range(2, n - 1):
            cnt = sum(nums[i] < nums[k] for i in range(k))
            for j in range(k - 1, 0, -1):
                if nums[j] > nums[k]:
                    g[j][k] = cnt
                else:
                    cnt -= 1
        return sum(
            f[j][k] * g[j][k] for j in range(1, n - 2) for k in range(j + 1, n - 1)
        )
speed

复杂度分析

指标
时间Depends on the final approach
空间Depends on the final approach
psychology

面试官常问的追问

外企场景
  • question_mark

    Understanding dynamic programming and state transitions is crucial for solving this problem.

  • question_mark

    Ability to optimize with binary indexed trees and prefix sums shows proficiency in handling large input sizes.

  • question_mark

    The ability to loop efficiently over (j, k) pairs without redundant computations is key to solving the problem within constraints.

warning

常见陷阱

外企场景
  • error

    Forgetting to check that the indices i < j < k < l, which is a crucial part of the problem's constraints.

  • error

    Not using optimization techniques like binary indexed trees or prefix sums for larger arrays, which can lead to time limits being exceeded.

  • error

    Incorrectly counting quadruplets by overlooking the order of indices or invalid combinations (i.e., nums[i] > nums[j]).

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Variation 1: Consider the problem with duplicates and modify the algorithm to account for them.

  • arrow_right_alt

    Variation 2: Count the quadruplets under additional constraints such as maximum or minimum values for certain elements.

  • arrow_right_alt

    Variation 3: Modify the problem to return the quadruplet values themselves instead of just the count.

help

常见问题

外企场景

统计上升四元组题解:状态·转移·动态规划 | LeetCode #2552 困难