Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)]` 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]` 2
83-
84-
1 - 2,得 `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)

AltStyle によって変換されたページ (->オリジナル) /