40
40
41
41
<!-- 这里可写通用的实现逻辑 -->
42
42
43
- 动态规划,我们规定 ` dp[i][j] ` 表示 ` i ` 个数字恰好拥有 ` j ` 个逆序对的不同数组的个数,最终答案为 ` dp[n][k] `
43
+ ** 方法一: 动态规划 + 前缀和 **
44
44
45
- 思考如何得到 ` dp [i][j]` ,假设 ` i - 1 ` 个数字已经确定,现在插入 ` i ` 一共有 ` i ` 种情况:
45
+ 我们定义 $f [ i] [ j ] $ 表示数组长度为 $i$,逆序对数为 $j$ 的数组个数。初始时 $f [ 0 ] [ 0 ] = 1$,其余 $f [ i ] [ j ] = 0$。
46
46
47
- - 放在第一个,由于 ` i ` 比之前的任何数都大,所以会产生 ` i - 1 ` 个逆序对,为了凑够 ` j ` 个逆序对,之前确定的数需要产生 ` j - (i - 1) ` 个逆序对
48
- - 放在第二个,产生 ` i - 2 ` 个逆序对,为了凑够 ` j ` 个逆序对,之前确定的数需要产生 ` j - (i - 2) ` 个逆序对
49
- - 放在第三个......同理
50
- - 放在最后一个,产生 ` 0 ` 个逆序对,之前确认的数需要产生 ` j ` 个逆序对
47
+ 接下来我们考虑如何得到 $f[ i] [ j ] $。
51
48
52
- 可得状态转移公式: ` dp[i][j] = dp[i - 1][j - (i - 1)] + ... + dp[i - 1][j] `
49
+ 假设前 $i-1$ 个数已经确定,现在要插入数字 $i$,我们讨论 $i$ 插入到每个位置的情况:
53
50
54
- 看到这种累加,很容易想到需要用前缀和进行优化。最终 ` dp[i][] ` 只依赖前缀和数组,甚至连 ` dp[i - 1][] ` 都不需要,所以可以进一步用一维数组优化空间
51
+ - 如果 $i$ 插入到第 $1$ 个位置,那么逆序对增加了 $i-1$ 个,所以 $f[ i] [ j ] +=f[ i-1] [ j-(i-1) ] $。
52
+ - 如果 $i$ 插入到第 $2$ 个位置,那么逆序对增加了 $i-2$ 个,所以 $f[ i] [ j ] +=f[ i-1] [ j-(i-2) ] $。
53
+ - ...
54
+ - 如果 $i$ 插入到第 $i-1$ 个位置,那么逆序对增加了 $1$ 个,所以 $f[ i] [ j ] +=f[ i-1] [ j-1 ] $。
55
+ - 如果 $i$ 插入到第 $i$ 个位置,那么逆序对不变,所以 $f[ i] [ j ] +=f[ i-1] [ j ] $。
56
+
57
+ 所以 $f[ i] [ j ] =\sum_ {k=1}^{i}f[ i-1] [ j-(i-k) ] $。
58
+
59
+ 我们注意到 $f[ i] [ j ] $ 的计算实际上涉及到前缀和,因此,我们可以使用前缀和优化计算过程。并且,由于 $f[ i] [ j ] $ 只与 $f[ i-1] [ j ] $ 有关,因此我们可以用一个一维数组来优化空间复杂度。
60
+
61
+ 时间复杂度 $O(n \times k)$,空间复杂度 $O(k)$。其中 $n$ 和 $k$ 分别为数组长度和逆序对数。
55
62
56
63
<!-- tabs:start -->
57
64
62
69
``` python
63
70
class Solution :
64
71
def kInversePairs (self , n : int , k : int ) -> int :
65
- mod = 1000000007
66
- dp, pre = [0 ] * (k + 1 ), [0 ] * (k + 2 )
72
+ mod = 10 ** 9 + 7
73
+ f = [1 ] + [0 ] * k
74
+ s = [0 ] * (k + 2 )
67
75
for i in range (1 , n + 1 ):
68
- dp[0 ] = 1
69
-
70
- # dp[i][j] = dp[i - 1][j - (i - 1)] + ... + dp[i - 1][j]
71
76
for j in range (1 , k + 1 ):
72
- dp[j] = (pre[j + 1 ] - pre[max (0 , j - i + 1 )] + mod) % mod
73
-
77
+ f[j] = (s[j + 1 ] - s[max (0 , j - (i - 1 ))]) % mod
74
78
for j in range (1 , k + 2 ):
75
- pre[j] = (pre[j - 1 ] + dp[j - 1 ]) % mod
76
-
77
- return dp[k]
78
- ```
79
-
80
- ` dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] + dp[i - 1][j - 2] + ... + dp[i - 1][j - (i - 1)] ` ①
81
-
82
- ` dp[i][j - 1] = dp[i - 1][j - 1] + dp[i - 1][j - 2] + ... + dp[i - 1][j - (i - 1)] + dp[i - 1][j - i] ` ②
83
-
84
- ① - ②,得 ` dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][j - i] `
85
-
86
- ``` python
87
- class Solution :
88
- def kInversePairs (self , n : int , k : int ) -> int :
89
- N, MOD = 1010 , int (1e9 ) + 7
90
- dp = [[0 ] * N for _ in range (N)]
91
- dp[1 ][0 ] = 1
92
- for i in range (2 , n + 1 ):
93
- dp[i][0 ] = 1
94
- for j in range (1 , k + 1 ):
95
- dp[i][j] = dp[i - 1 ][j] + dp[i][j - 1 ]
96
- if j >= i:
97
- dp[i][j] -= dp[i - 1 ][j - i]
98
- dp[i][j] %= MOD
99
- return dp[n][k]
100
- ```
101
-
102
- 空间优化:
103
-
104
- ``` python
105
- class Solution :
106
- def kInversePairs (self , n : int , k : int ) -> int :
107
- N, MOD = 1010 , int (1e9 ) + 7
108
- dp = [0 ] * N
109
- dp[0 ] = 1
110
- for i in range (2 , n + 1 ):
111
- t = dp.copy()
112
- for j in range (1 , k + 1 ):
113
- dp[j] = t[j] + dp[j - 1 ]
114
- if j >= i:
115
- dp[j] -= t[j - i]
116
- dp[j] %= MOD
117
- return dp[k]
79
+ s[j] = (s[j - 1 ] + f[j - 1 ]) % mod
80
+ return f[k]
118
81
```
119
82
120
83
### ** Java**
@@ -123,70 +86,72 @@ class Solution:
123
86
124
87
``` java
125
88
class Solution {
126
-
127
- private static final int MOD = 1000000007 ;
128
-
129
89
public int kInversePairs (int n , int k ) {
130
- int [] dp = new int [k + 1 ];
131
- int [] pre = new int [k + 2 ];
132
- for (int i = 1 ; i <= n; i++ ) {
133
- dp[0 ] = 1 ;
134
-
135
- // dp[i][j] = dp[i - 1][j - (i - 1)] + ... + dp[i - 1][j]
136
- for (int j = 1 ; j <= k; j++ ) {
137
- dp[j] = (pre[j + 1 ] - pre[Math . max(0 , j - i + 1 )] + MOD ) % MOD ;
90
+ final int mod = (int ) 1e9 + 7 ;
91
+ int [] f = new int [k + 1 ];
92
+ int [] s = new int [k + 2 ];
93
+ f[0 ] = 1 ;
94
+ Arrays . fill(s, 1 );
95
+ s[0 ] = 0 ;
96
+ for (int i = 1 ; i <= n; ++ i) {
97
+ for (int j = 1 ; j <= k; ++ j) {
98
+ f[j] = (s[j + 1 ] - s[Math . max(0 , j - (i - 1 ))] + mod) % mod;
138
99
}
139
-
140
- for (int j = 1 ; j <= k + 1 ; j++ ) {
141
- pre[j] = (pre[j - 1 ] + dp[j - 1 ]) % MOD ;
100
+ for (int j = 1 ; j <= k + 1 ; ++ j) {
101
+ s[j] = (s[j - 1 ] + f[j - 1 ]) % mod;
142
102
}
143
103
}
144
- return dp [k];
104
+ return f [k];
145
105
}
146
106
}
147
107
```
148
108
149
- ``` java
109
+ ### ** C++**
110
+
111
+ ``` cpp
150
112
class Solution {
151
- public int kInversePairs (int n , int k ) {
152
- int N = 1010 , MOD = (int ) (1e9 + 7 );
153
- int [][] dp = new int [N ][N ];
154
- dp[1 ][0 ] = 1 ;
155
- for (int i = 2 ; i < n + 1 ; ++ i) {
156
- dp[i][0 ] = 1 ;
157
- for (int j = 1 ; j < k + 1 ; ++ j) {
158
- dp[i][j] = (dp[i - 1 ][j] + dp[i][j - 1 ]) % MOD ;
159
- if (j >= i) {
160
- dp[i][j] = (dp[i][j] - dp[i - 1 ][j - i] + MOD ) % MOD ;
161
- }
113
+ public:
114
+ int kInversePairs(int n, int k) {
115
+ int f[ k + 1] ;
116
+ int s[ k + 2] ;
117
+ memset(f, 0, sizeof(f));
118
+ f[ 0] = 1;
119
+ fill(s, s + k + 2, 1);
120
+ s[ 0] = 0;
121
+ const int mod = 1e9 + 7;
122
+ for (int i = 1; i <= n; ++i) {
123
+ for (int j = 1; j <= k; ++j) {
124
+ f[ j] = (s[ j + 1] - s[ max(0, j - (i - 1))] + mod) % mod;
125
+ }
126
+ for (int j = 1; j <= k + 1; ++j) {
127
+ s[ j] = (s[ j - 1] + f[ j - 1] ) % mod;
162
128
}
163
129
}
164
- return dp[n] [k];
130
+ return f [ k] ;
165
131
}
166
- }
132
+ };
167
133
```
168
134
169
135
### **Go**
170
136
171
137
```go
172
- const mod int = 1e9 + 7
173
-
174
138
func kInversePairs(n int, k int) int {
175
- dp := make ([]int , k+1 )
176
- pre := make ([]int , k+2 )
139
+ f := make([]int, k+1)
140
+ s := make([]int, k+2)
141
+ f[0] = 1
142
+ for i, x := range f {
143
+ s[i+1] = s[i] + x
144
+ }
145
+ const mod = 1e9 + 7
177
146
for i := 1; i <= n; i++ {
178
- dp[0 ] = 1
179
-
180
- // dp[i][j] = dp[i - 1][j - (i - 1)] + ... + dp[i - 1][j]
181
147
for j := 1; j <= k; j++ {
182
- dp [j] = (pre [j+1 ] - pre [max (0 , j-i+ 1 )] + mod) % mod
148
+ f [j] = (s [j+1] - s [max(0, j-(i-1) )] + mod) % mod
183
149
}
184
-
185
150
for j := 1; j <= k+1; j++ {
186
- pre [j] = (pre [j-1 ] + dp [j-1 ]) % mod
151
+ s [j] = (s [j-1] + f [j-1]) % mod
187
152
}
188
153
}
189
- return dp [k]
154
+ return f [k]
190
155
}
191
156
192
157
func max(a, b int) int {
@@ -197,31 +162,25 @@ func max(a, b int) int {
197
162
}
198
163
```
199
164
200
- ### ** C++**
201
-
202
- ``` cpp
203
- class Solution {
204
- private:
205
- static constexpr int MOD = 1e9 + 7;
206
-
207
- public:
208
- int kInversePairs(int n, int k) {
209
- vector<int > dp(k + 1), pre(k + 2, 0);
210
- for (int i = 1; i <= n; ++i) {
211
- dp[ 0] = 1;
212
-
213
- // dp[i][j] = dp[i - 1][j - (i - 1)] + ... + dp[i - 1][j]
214
- for (int j = 1; j <= k; ++j) {
215
- dp[j] = (pre[j + 1] - pre[max(0, j - i + 1)] + MOD) % MOD;
216
- }
217
-
218
- for (int j = 1 ; j <= k + 1 ; ++j) {
219
- pre[j] = (pre[j - 1] + dp[j - 1]) % MOD;
220
- }
165
+ ### ** TypeScript**
166
+
167
+ ``` ts
168
+ function kInversePairs(n : number , k : number ): number {
169
+ const f: number [] = new Array (k + 1 ).fill (0 );
170
+ f [0 ] = 1 ;
171
+ const s: number [] = new Array (k + 2 ).fill (1 );
172
+ s [0 ] = 0 ;
173
+ const mod: number = 1e9 + 7 ;
174
+ for (let i = 1 ; i <= n ; ++ i ) {
175
+ for (let j = 1 ; j <= k ; ++ j ) {
176
+ f [j ] = (s [j + 1 ] - s [Math .max (0 , j - (i - 1 ))] + mod ) % mod ;
177
+ }
178
+ for (let j = 1 ; j <= k + 1 ; ++ j ) {
179
+ s [j ] = (s [j - 1 ] + f [j - 1 ]) % mod ;
221
180
}
222
- return dp[k];
223
181
}
224
- };
182
+ return f [k ];
183
+ }
225
184
```
226
185
227
186
### ** ...**
0 commit comments