LeetCode 题解工作台

统计逆序对的数目

给你一个整数 n 和一个二维数组 requirements ,其中 requirements[i] = [end i , cnt i ] 表示这个要求中的末尾下标和 逆序对 的数目。 整数数组 nums 中一个下标对 (i, j) 如果满足以下条件,那么它们被称为一个 逆序对 : i 且 nums[…

category

2

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

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

bolt

答案摘要

我们定义 表示 的排列中,逆序对数量为 的排列数。考虑下标为 的数 与前面 个数的大小关系。如果 比前面 个数小,那么前面的 个数与 都构成了逆序对,逆序对数量为 。因此,我们可以得到状态转移方程: $$

Interview AiBox logo

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

试试 AiBox 面试助手arrow_forward
description

题目描述

给你一个整数 n 和一个二维数组 requirements ,其中 requirements[i] = [endi, cnti] 表示这个要求中的末尾下标和 逆序对 的数目。

整数数组 nums 中一个下标对 (i, j) 如果满足以下条件,那么它们被称为一个 逆序对 :

  • i < j 且 nums[i] > nums[j]

请你返回 [0, 1, 2, ..., n - 1] 的 排列 perm 的数目,满足对 所有 的 requirements[i] 都满足 perm[0..endi] 中恰好有 cnti 个逆序对。

由于答案可能会很大,将它对 109 + 7 取余 后返回。

 

示例 1:

输入:n = 3, requirements = [[2,2],[0,0]]

输出:2

解释:

两个排列为:

  • [2, 0, 1]
    • 前缀 [2, 0, 1] 的逆序对为 (0, 1) 和 (0, 2) 。
    • 前缀 [2] 的逆序对数目为 0 个。
  • [1, 2, 0]
    • 前缀 [1, 2, 0] 的逆序对为 (0, 2) 和 (1, 2) 。
    • 前缀 [1] 的逆序对数目为 0 个。

示例 2:

输入:n = 3, requirements = [[2,2],[1,1],[0,0]]

输出:1

解释:

唯一满足要求的排列是 [2, 0, 1] :

  • 前缀 [2, 0, 1] 的逆序对为 (0, 1) 和 (0, 2) 。
  • 前缀 [2, 0] 的逆序对为 (0, 1) 。
  • 前缀 [2] 的逆序对数目为 0 。

示例 3:

输入:n = 2, requirements = [[0,0],[1,0]]

输出:1

解释:

唯一满足要求的排列为 [0, 1] :

  • 前缀 [0] 的逆序对数目为 0 。
  • 前缀 [0, 1] 没有逆序对。
 

 

提示:

  • 2 <= n <= 300
  • 1 <= requirements.length <= n
  • requirements[i] = [endi, cnti]
  • 0 <= endi <= n - 1
  • 0 <= cnti <= 400
  • 输入保证至少有一个 i 满足 endi == n - 1 。
  • 输入保证所有的 endi 互不相同。
lightbulb

解题思路

方法一:动态规划

我们定义 f[i][j]f[i][j] 表示 [0..i][0..i] 的排列中,逆序对数量为 jj 的排列数。考虑下标为 ii 的数 aia_i 与前面 ii 个数的大小关系。如果 aia_i 比前面 kk 个数小,那么前面的 kk 个数与 aia_i 都构成了逆序对,逆序对数量为 kk。因此,我们可以得到状态转移方程:

f[i][j]=k=0min(i,j)f[i1][jk]f[i][j] = \sum_{k=0}^{\min(i, j)} f[i-1][j-k]

由于题目要求 [0..endi][0..\textit{end}_i] 的逆序对数量为 cnti\textit{cnt}_i,因此,当我们计算 i=endii = \textit{end}_i 时,我们只需要计算 f[i][cnti]f[i][\textit{cnt}_i] 即可。其余的 f[i][..]f[i][..] 都为 00

时间复杂度 O(n×m×min(n,m))O(n \times m \times \min(n, m)),空间复杂度 O(n×m)O(n \times m)。其中 mm 是逆序对数量的最大值。本题中 m400m \le 400

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution:
    def numberOfPermutations(self, n: int, requirements: List[List[int]]) -> int:
        req = [-1] * n
        for end, cnt in requirements:
            req[end] = cnt
        if req[0] > 0:
            return 0
        req[0] = 0
        mod = 10**9 + 7
        m = max(req)
        f = [[0] * (m + 1) for _ in range(n)]
        f[0][0] = 1
        for i in range(1, n):
            l, r = 0, m
            if req[i] >= 0:
                l = r = req[i]
            for j in range(l, r + 1):
                for k in range(min(i, j) + 1):
                    f[i][j] = (f[i][j] + f[i - 1][j - k]) % mod
        return f[n - 1][req[n - 1]]
speed

复杂度分析

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

面试官常问的追问

外企场景
  • question_mark

    Candidate understands the concept of dynamic programming for state transitions.

  • question_mark

    Candidate can efficiently calculate and update inversion counts using data structures like Fenwick Tree.

  • question_mark

    Candidate identifies the challenge of handling multiple requirements and can incorporate them into the DP approach.

warning

常见陷阱

外企场景
  • error

    Not accounting for all inversion constraints, which can lead to incorrect permutation counts.

  • error

    Inefficient inversion counting leading to excessive time complexity.

  • error

    Failure to properly update the DP table when new elements are added, causing incorrect counts of valid permutations.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Modify the problem to handle permutations with additional constraints on element values.

  • arrow_right_alt

    Add a requirement to count the number of inversions for subsets of the array, not just prefixes.

  • arrow_right_alt

    Allow the inversion count to be variable for each prefix, testing how the algorithm handles different ranges of inversion constraints.

help

常见问题

外企场景

统计逆序对的数目题解:状态·转移·动态规划 | LeetCode #3193 困难