Skip to content

Commit 170c10f

Browse files
committed
feat: add solutions to lc problem: No.0629
No.0629.K Inverse Pairs Array
1 parent d9179c2 commit 170c10f

File tree

8 files changed

+203
-282
lines changed

8 files changed

+203
-282
lines changed

solution/0600-0699/0629.K Inverse Pairs Array/README.md

Lines changed: 80 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,25 @@
4040

4141
<!-- 这里可写通用的实现逻辑 -->
4242

43-
动态规划,我们规定 `dp[i][j]` 表示 `i` 个数字恰好拥有 `j` 个逆序对的不同数组的个数,最终答案为 `dp[n][k]`
43+
**方法一:动态规划 + 前缀和**
4444

45-
思考如何得到 `dp[i][j]`,假设 `i - 1` 个数字已经确定,现在插入 `i` 一共有 `i` 种情况:
45+
我们定义 $f[i][j]$ 表示数组长度为 $i$,逆序对数为 $j$ 的数组个数。初始时 $f[0][0] = 1$,其余 $f[i][j] = 0$。
4646

47-
- 放在第一个,由于 `i` 比之前的任何数都大,所以会产生 `i - 1` 个逆序对,为了凑够 `j` 个逆序对,之前确定的数需要产生 `j - (i - 1)` 个逆序对
48-
- 放在第二个,产生 `i - 2` 个逆序对,为了凑够 `j` 个逆序对,之前确定的数需要产生 `j - (i - 2)` 个逆序对
49-
- 放在第三个......同理
50-
- 放在最后一个,产生 `0` 个逆序对,之前确认的数需要产生 `j` 个逆序对
47+
接下来我们考虑如何得到 $f[i][j]$。
5148

52-
可得状态转移公式:`dp[i][j] = dp[i - 1][j - (i - 1)] + ... + dp[i - 1][j]`
49+
假设前 $i-1$ 个数已经确定,现在要插入数字 $i$,我们讨论 $i$ 插入到每个位置的情况:
5350

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$ 分别为数组长度和逆序对数。
5562

5663
<!-- tabs:start -->
5764

@@ -62,59 +69,15 @@
6269
```python
6370
class Solution:
6471
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)
6775
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]
7176
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
7478
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]
11881
```
11982

12083
### **Java**
@@ -123,70 +86,72 @@ class Solution:
12386

12487
```java
12588
class Solution {
126-
127-
private static final int MOD = 1000000007;
128-
12989
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;
13899
}
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;
142102
}
143103
}
144-
return dp[k];
104+
return f[k];
145105
}
146106
}
147107
```
148108

149-
```java
109+
### **C++**
110+
111+
```cpp
150112
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;
162128
}
163129
}
164-
return dp[n][k];
130+
return f[k];
165131
}
166-
}
132+
};
167133
```
168134
169135
### **Go**
170136
171137
```go
172-
const mod int = 1e9 + 7
173-
174138
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
177146
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]
181147
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
183149
}
184-
185150
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
187152
}
188153
}
189-
return dp[k]
154+
return f[k]
190155
}
191156
192157
func max(a, b int) int {
@@ -197,31 +162,25 @@ func max(a, b int) int {
197162
}
198163
```
199164

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;
221180
}
222-
return dp[k];
223181
}
224-
};
182+
return f[k];
183+
}
225184
```
226185

227186
### **...**

0 commit comments

Comments
 (0)