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 fa38c56

Browse files
feat: add solutions to lc problem: No.3343 (doocs#3710)
No.3343.Count Number of Balanced Permutations
1 parent 7f9a026 commit fa38c56

File tree

11 files changed

+860
-12
lines changed

11 files changed

+860
-12
lines changed

‎solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3341.Fi
8484

8585
<!-- solution:start -->
8686

87-
### 方法一
87+
### 方法一:Dijkstra 算法
88+
89+
我们定义一个二维数组 $\textit{dist},ドル其中 $\textit{dist}[i][j]$ 表示从起点到达房间 $(i, j)$ 所需的最少时间。初始时,我们将 $\textit{dist}$ 数组中的所有元素设为无穷大,然后将起点 $(0, 0)$ 的 $\textit{dist}$ 值设为 0ドル$。
90+
91+
我们使用优先队列 $\textit{pq}$ 存储每一个状态,其中每个状态由三个值 $(d, i, j)$ 组成,表示从起点到达房间 $(i, j)$ 所需的时间为 $d$。初始时,我们将起点 $(0, 0, 0)$ 加入到 $\textit{pq}$ 中。
92+
93+
在每一次迭代中,我们取出 $\textit{pq}$ 中的队首元素 $(d, i, j),ドル如果 $(i, j)$ 是终点,那么我们返回 $d$。如果 $d$ 大于 $\textit{dist}[i][j],ドル那么我们跳过这个状态。否则,我们枚举 $(i, j)$ 的四个相邻位置 $(x, y),ドル如果 $(x, y)$ 在地图内,那么我们计算从 $(i, j)$ 到 $(x, y)$ 的最终时间 $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + 1,ドル如果 $t$ 小于 $\textit{dist}[x][y],ドル那么我们更新 $\textit{dist}[x][y]$ 的值,并将 $(t, x, y)$ 加入到 $\textit{pq}$ 中。
94+
95+
时间复杂度 $O(n \times m \times \log (n \times m)),ドル空间复杂度 $O(n \times m)$。其中 $n$ 和 $m$ 分别是地图的行数和列数。
8896

8997
<!-- tabs:start -->
9098

‎solution/3300-3399/3341.Find Minimum Time to Reach Last Room I/README_EN.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3341.Fi
8181

8282
<!-- solution:start -->
8383

84-
### Solution 1
84+
### Solution 1: Dijkstra's Algorithm
85+
86+
We define a two-dimensional array $\textit{dist},ドル where $\textit{dist}[i][j]$ represents the minimum time required to reach room $(i, j)$ from the starting point. Initially, we set all elements in the $\textit{dist}$ array to infinity, and then set the $\textit{dist}$ value of the starting point $(0, 0)$ to 0ドル$.
87+
88+
We use a priority queue $\textit{pq}$ to store each state, where each state consists of three values $(d, i, j),ドル representing the time $d$ required to reach room $(i, j)$ from the starting point. Initially, we add the starting point $(0, 0, 0)$ to $\textit{pq}$.
89+
90+
In each iteration, we take the front element $(d, i, j)$ from $\textit{pq}$. If $(i, j)$ is the endpoint, we return $d$. If $d$ is greater than $\textit{dist}[i][j],ドル we skip this state. Otherwise, we enumerate the four adjacent positions $(x, y)$ of $(i, j)$. If $(x, y)$ is within the map, we calculate the final time $t$ from $(i, j)$ to $(x, y)$ as $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + 1$. If $t$ is less than $\textit{dist}[x][y],ドル we update the value of $\textit{dist}[x][y]$ and add $(t, x, y)$ to $\textit{pq}$.
91+
92+
The time complexity is $O(n \times m \times \log (n \times m)),ドル and the space complexity is $O(n \times m)$. Here, $n$ and $m$ are the number of rows and columns of the map, respectively.
8593

8694
<!-- tabs:start -->
8795

‎solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3342.Fi
8585

8686
<!-- solution:start -->
8787

88-
### 方法一
88+
### 方法一:Dijkstra 算法
89+
90+
我们定义一个二维数组 $\textit{dist},ドル其中 $\textit{dist}[i][j]$ 表示从起点到达房间 $(i, j)$ 所需的最少时间。初始时,我们将 $\textit{dist}$ 数组中的所有元素设为无穷大,然后将起点 $(0, 0)$ 的 $\textit{dist}$ 值设为 0ドル$。
91+
92+
我们使用优先队列 $\textit{pq}$ 存储每一个状态,其中每个状态由三个值 $(d, i, j)$ 组成,表示从起点到达房间 $(i, j)$ 所需的时间为 $d$。初始时,我们将起点 $(0, 0, 0)$ 加入到 $\textit{pq}$ 中。
93+
94+
在每一次迭代中,我们取出 $\textit{pq}$ 中的队首元素 $(d, i, j),ドル如果 $(i, j)$ 是终点,那么我们返回 $d$。如果 $d$ 大于 $\textit{dist}[i][j],ドル那么我们跳过这个状态。否则,我们枚举 $(i, j)$ 的四个相邻位置 $(x, y),ドル如果 $(x, y)$ 在地图内,那么我们计算从 $(i, j)$ 到 $(x, y)$ 的最终时间 $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + (i + 2) \bmod 2 + 1,ドル如果 $t$ 小于 $\textit{dist}[x][y],ドル那么我们更新 $\textit{dist}[x][y]$ 的值,并将 $(t, x, y)$ 加入到 $\textit{pq}$ 中。
95+
96+
时间复杂度 $O(n \times m \times \log (n \times m)),ドル空间复杂度 $O(n \times m)$。其中 $n$ 和 $m$ 分别是地图的行数和列数。
8997

9098
<!-- tabs:start -->
9199

‎solution/3300-3399/3342.Find Minimum Time to Reach Last Room II/README_EN.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,15 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3342.Fi
8282

8383
<!-- solution:start -->
8484

85-
### Solution 1
85+
### Solution 1: Dijkstra's Algorithm
86+
87+
We define a two-dimensional array $\textit{dist},ドル where $\textit{dist}[i][j]$ represents the minimum time required to reach room $(i, j)$ from the starting point. Initially, we set all elements in the $\textit{dist}$ array to infinity, and then set the $\textit{dist}$ value of the starting point $(0, 0)$ to 0ドル$.
88+
89+
We use a priority queue $\textit{pq}$ to store each state, where each state consists of three values $(d, i, j),ドル representing the time $d$ required to reach room $(i, j)$ from the starting point. Initially, we add the starting point $(0, 0, 0)$ to $\textit{pq}$.
90+
91+
In each iteration, we take the front element $(d, i, j)$ from $\textit{pq}$. If $(i, j)$ is the endpoint, we return $d$. If $d$ is greater than $\textit{dist}[i][j],ドル we skip this state. Otherwise, we enumerate the four adjacent positions $(x, y)$ of $(i, j)$. If $(x, y)$ is within the map, we calculate the final time $t$ from $(i, j)$ to $(x, y)$ as $t = \max(\textit{moveTime}[x][y], \textit{dist}[i][j]) + (i + j) \bmod 2 + 1$. If $t$ is less than $\textit{dist}[x][y],ドル we update the value of $\textit{dist}[x][y]$ and add $(t, x, y)$ to $\textit{pq}$.
92+
93+
The time complexity is $O(n \times m \times \log (n \times m)),ドル and the space complexity is $O(n \times m)$. Here, $n$ and $m$ are the number of rows and columns of the map, respectively.
8694

8795
<!-- tabs:start -->
8896

‎solution/3300-3399/3343.Count Number of Balanced Permutations/README.md‎

Lines changed: 281 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,32 +85,309 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3343.Co
8585

8686
<!-- solution:start -->
8787

88-
### 方法一
88+
### 方法一:记忆化搜索 + 组合数学
89+
90+
我们首先统计出字符串 $\textit{num}$ 中每个数字出现的次数,记录在数组 $\textit{cnt}$ 中,然后计算出字符串 $\textit{num}$ 的总和 $\textit{s}$。
91+
92+
如果 $\textit{s}$ 是奇数,那么 $\textit{num}$ 一定不是平衡的,直接返回 0ドル$。
93+
94+
接下来,我们定义记忆化搜索函数 $\text{dfs}(i, j, a, b),ドル其中 $i$ 表示当前要从数字 $i$ 开始填充,而 $j$ 表示奇数位剩余待填的数字之和,而 $a$ 和 $b$ 分别表示奇数位和偶数位剩余待填的数字个数。我们记字符串 $\textit{num}$ 的长度为 $n,ドル那么答案就是 $\text{dfs}(0, s / 2, n / 2, (n + 1) / 2)$。
95+
96+
在 $\text{dfs}(i, j, a, b)$ 函数中,我们首先判断是否已经填充完了所有的数字,如果是的话,此时需要满足 $j = 0$ 且 $a = 0$ 且 $b = 0,ドル若满足这个条件,说明当前的排列是平衡的,返回 1ドル,ドル否则返回 0ドル$。
97+
98+
接下来,我们判断当前奇数位剩余待填的数字个数 $a$ 是否为 0ドル$ 且 $j > 0,ドル如果是的话,说明当前的排列不是平衡的,提前返回 0ドル$。
99+
100+
否则,我们可以枚举当前数字分配给奇数位的数字个数 $l,ドル那么偶数位的数字个数就是 $r = \textit{cnt}[i] - l,ドル我们需要满足 0ドル \leq r \leq b$ 且 $l \times i \leq j,ドル然后我们计算出当前的方案数 $t = C_a^l \times C_b^r \times \text{dfs}(i + 1, j - l \times i, a - l, b - r),ドル最后答案就是所有方案数之和。
101+
102+
时间复杂度 $O(|\Sigma| \times n^2 \times (n + |\Sigma|)),ドル其中 $|\Sigma|$ 表示数字的种类数,本题中 $|\Sigma| = 10$。空间复杂度 $O(n^2 \times |\Sigma|^2)$。
89103

90104
<!-- tabs:start -->
91105

92106
#### Python3
93107

94108
```python
95-
109+
class Solution:
110+
def countBalancedPermutations(self, num: str) -> int:
111+
@cache
112+
def dfs(i: int, j: int, a: int, b: int) -> int:
113+
if i > 9:
114+
return (j | a | b) == 0
115+
if a == 0 and j:
116+
return 0
117+
ans = 0
118+
for l in range(min(cnt[i], a) + 1):
119+
r = cnt[i] - l
120+
if 0 <= r <= b and l * i <= j:
121+
t = comb(a, l) * comb(b, r) * dfs(i + 1, j - l * i, a - l, b - r)
122+
ans = (ans + t) % mod
123+
return ans
124+
125+
nums = list(map(int, num))
126+
s = sum(nums)
127+
if s % 2:
128+
return 0
129+
n = len(nums)
130+
mod = 10**9 + 7
131+
cnt = Counter(nums)
132+
return dfs(0, s // 2, n // 2, (n + 1) // 2)
96133
```
97134

98135
#### Java
99136

100137
```java
101-
138+
class Solution {
139+
private final int[] cnt = new int[10];
140+
private final int mod = (int) 1e9 + 7;
141+
private Integer[][][][] f;
142+
private long[][] c;
143+
144+
public int countBalancedPermutations(String num) {
145+
int s = 0;
146+
for (char c : num.toCharArray()) {
147+
cnt[c - '0']++;
148+
s += c - '0';
149+
}
150+
if (s % 2 == 1) {
151+
return 0;
152+
}
153+
int n = num.length();
154+
int m = n / 2 + 1;
155+
f = new Integer[10][s / 2 + 1][m][m + 1];
156+
c = new long[m + 1][m + 1];
157+
c[0][0] = 1;
158+
for (int i = 1; i <= m; i++) {
159+
c[i][0] = 1;
160+
for (int j = 1; j <= i; j++) {
161+
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
162+
}
163+
}
164+
return dfs(0, s / 2, n / 2, (n + 1) / 2);
165+
}
166+
167+
private int dfs(int i, int j, int a, int b) {
168+
if (i > 9) {
169+
return ((j | a | b) == 0) ? 1 : 0;
170+
}
171+
if (a == 0 && j != 0) {
172+
return 0;
173+
}
174+
if (f[i][j][a][b] != null) {
175+
return f[i][j][a][b];
176+
}
177+
int ans = 0;
178+
for (int l = 0; l <= Math.min(cnt[i], a); ++l) {
179+
int r = cnt[i] - l;
180+
if (r >= 0 && r <= b && l * i <= j) {
181+
int t = (int) (c[a][l] * c[b][r] % mod * dfs(i + 1, j - l * i, a - l, b - r) % mod);
182+
ans = (ans + t) % mod;
183+
}
184+
}
185+
return f[i][j][a][b] = ans;
186+
}
187+
}
102188
```
103189

104190
#### C++
105191

106192
```cpp
107-
193+
using ll = long long;
194+
const int MX = 80;
195+
const int MOD = 1e9 + 7;
196+
ll c[MX][MX];
197+
198+
auto init = [] {
199+
c[0][0] = 1;
200+
for (int i = 1; i < MX; ++i) {
201+
c[i][0] = 1;
202+
for (int j = 1; j <= i; ++j) {
203+
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
204+
}
205+
}
206+
return 0;
207+
}();
208+
209+
class Solution {
210+
public:
211+
int countBalancedPermutations(string num) {
212+
int cnt[10]{};
213+
int s = 0;
214+
for (char& c : num) {
215+
++cnt[c - '0'];
216+
s += c - '0';
217+
}
218+
if (s % 2) {
219+
return 0;
220+
}
221+
int n = num.size();
222+
int m = n / 2 + 1;
223+
int f[10][s / 2 + 1][m][m + 1];
224+
memset(f, -1, sizeof(f));
225+
auto dfs = [&](auto&& dfs, int i, int j, int a, int b) -> int {
226+
if (i > 9) {
227+
return ((j | a | b) == 0 ? 1 : 0);
228+
}
229+
if (a == 0 && j) {
230+
return 0;
231+
}
232+
if (f[i][j][a][b] != -1) {
233+
return f[i][j][a][b];
234+
}
235+
int ans = 0;
236+
for (int l = 0; l <= min(cnt[i], a); ++l) {
237+
int r = cnt[i] - l;
238+
if (r >= 0 && r <= b && l * i <= j) {
239+
int t = c[a][l] * c[b][r] % MOD * dfs(dfs, i + 1, j - l * i, a - l, b - r) % MOD;
240+
ans = (ans + t) % MOD;
241+
}
242+
}
243+
return f[i][j][a][b] = ans;
244+
};
245+
return dfs(dfs, 0, s / 2, n / 2, (n + 1) / 2);
246+
}
247+
};
108248
```
109249
110250
#### Go
111251
112252
```go
253+
const (
254+
MX = 80
255+
MOD = 1_000_000_007
256+
)
257+
258+
var c [MX][MX]int
259+
260+
func init() {
261+
c[0][0] = 1
262+
for i := 1; i < MX; i++ {
263+
c[i][0] = 1
264+
for j := 1; j <= i; j++ {
265+
c[i][j] = (c[i-1][j] + c[i-1][j-1]) % MOD
266+
}
267+
}
268+
}
269+
270+
func countBalancedPermutations(num string) int {
271+
var cnt [10]int
272+
s := 0
273+
for _, ch := range num {
274+
cnt[ch-'0']++
275+
s += int(ch - '0')
276+
}
277+
278+
if s%2 != 0 {
279+
return 0
280+
}
281+
282+
n := len(num)
283+
m := n/2 + 1
284+
f := make([][][][]int, 10)
285+
for i := range f {
286+
f[i] = make([][][]int, s/2+1)
287+
for j := range f[i] {
288+
f[i][j] = make([][]int, m)
289+
for k := range f[i][j] {
290+
f[i][j][k] = make([]int, m+1)
291+
for l := range f[i][j][k] {
292+
f[i][j][k][l] = -1
293+
}
294+
}
295+
}
296+
}
297+
298+
var dfs func(i, j, a, b int) int
299+
dfs = func(i, j, a, b int) int {
300+
if i > 9 {
301+
if j == 0 && a == 0 && b == 0 {
302+
return 1
303+
}
304+
return 0
305+
}
306+
if a == 0 && j > 0 {
307+
return 0
308+
}
309+
if f[i][j][a][b] != -1 {
310+
return f[i][j][a][b]
311+
}
312+
ans := 0
313+
for l := 0; l <= min(cnt[i], a); l++ {
314+
r := cnt[i] - l
315+
if r >= 0 && r <= b && l*i <= j {
316+
t := c[a][l] * c[b][r] % MOD * dfs(i+1, j-l*i, a-l, b-r) % MOD
317+
ans = (ans + t) % MOD
318+
}
319+
}
320+
f[i][j][a][b] = ans
321+
return ans
322+
}
323+
324+
return dfs(0, s/2, n/2, (n+1)/2)
325+
}
326+
```
113327

328+
#### TypeScript
329+
330+
```ts
331+
const MX = 80;
332+
const MOD = 10 ** 9 + 7;
333+
const c: number[][] = Array.from({ length: MX }, () => Array(MX).fill(0));
334+
(function init() {
335+
c[0][0] = 1;
336+
for (let i = 1; i < MX; i++) {
337+
c[i][0] = 1;
338+
for (let j = 1; j <= i; j++) {
339+
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
340+
}
341+
}
342+
})();
343+
344+
function countBalancedPermutations(num: string): number {
345+
const cnt = Array(10).fill(0);
346+
let s = 0;
347+
for (const ch of num) {
348+
cnt[+ch]++;
349+
s += +ch;
350+
}
351+
352+
if (s % 2 !== 0) {
353+
return 0;
354+
}
355+
356+
const n = num.length;
357+
const m = Math.floor(n / 2) + 1;
358+
const f: Record<string, number> = {};
359+
360+
const dfs = (i: number, j: number, a: number, b: number): number => {
361+
if (i > 9) {
362+
return (j | a | b) === 0 ? 1 : 0;
363+
}
364+
if (a === 0 && j > 0) {
365+
return 0;
366+
}
367+
368+
const key = `${i},${j},${a},${b}`;
369+
if (key in f) {
370+
return f[key];
371+
}
372+
373+
let ans = 0;
374+
for (let l = 0; l <= Math.min(cnt[i], a); l++) {
375+
const r = cnt[i] - l;
376+
if (r >= 0 && r <= b && l * i <= j) {
377+
const t = Number(
378+
(((BigInt(c[a][l]) * BigInt(c[b][r])) % BigInt(MOD)) *
379+
BigInt(dfs(i + 1, j - l * i, a - l, b - r))) %
380+
BigInt(MOD),
381+
);
382+
ans = (ans + t) % MOD;
383+
}
384+
}
385+
f[key] = ans;
386+
return ans;
387+
};
388+
389+
return dfs(0, s / 2, Math.floor(n / 2), Math.floor((n + 1) / 2));
390+
}
114391
```
115392

116393
<!-- tabs:end -->

0 commit comments

Comments
(0)

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