Skip to content

Commit 8053ddf

Browse files
authored
feat: add solutions to lc problem: No.1467 (doocs#1485)
No.1467.Probability of a Two Boxes Having The Same Number of Distinct Balls
1 parent 3166181 commit 8053ddf

File tree

7 files changed

+662
-1
lines changed

7 files changed

+662
-1
lines changed

solution/1400-1499/1467.Probability of a Two Boxes Having The Same Number of Distinct Balls/README.md

Lines changed: 237 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,258 @@
6363

6464
<!-- 这里可写通用的实现逻辑 -->
6565

66+
**方法一:记忆化搜索 + 组合数学**
67+
68+
我们知道 $2n$ 个球,平均分到两个盒子中,总共有 $C_{2n}^n$ 种分法。接下来,我们可以求出每种分法中,两个盒子中球的颜色数相同的情况数。最后,将两者相除即可。
69+
70+
我们可以预处理出组合数 $C_{n}^m$,然后使用记忆化搜索求解。
71+
72+
设计一个函数 $dfs(i, j, diff)$,表示当前从第 $i$ 种球开始,第一个盒子剩余可放置 $j$ 个球,两个盒子中球的颜色数的差为 $diff$ 的方案数。
73+
74+
函数 $dfs(i, j, diff)$ 的执行逻辑如下:
75+
76+
- 如果 $i \geq k$,表示所有球都已经放完,如果 $j = 0$ 且 $diff = 0$,表示两个盒子中球的颜色数相同,返回 $1$,否则返回 $0$;
77+
- 如果 $j < 0$,表示第一个盒子中球的数量超过了 $n$,返回 $0$;
78+
- 如果 $f[i][j][diff]$ 不为 $-1$,表示已经计算过,直接返回 $f[i][j][diff]$;
79+
- 否则,枚举第 $i$ 种球放入第一个盒子中的数量 $x$,则第 $i$ 种球放入第二个盒子中的数量为 $balls[i] - x$,两个盒子中球的颜色数的变化量为 $y$。如果所有球都放入第一个盒子中,那么 $y = 1$;如果所有球都放入第二个盒子中,那么 $y = -1$;否则 $y = 0$。然后,递归计算 $dfs(i + 1, j - x, diff + y)$,并将结果与 $C_{balls[i]}^x$ 相乘,累加到答案中。最后,将答案存入 $f[i][j][diff]$ 中,并返回答案。
80+
81+
时间复杂度 $O(n^2 \times k^2)$,空间复杂度 $O(n \times k^2)$。其中 $n$ 和 $k$ 分别是球的总数和颜色的种数。
82+
6683
<!-- tabs:start -->
6784

6885
### **Python3**
6986

7087
<!-- 这里可写当前语言的特殊实现逻辑 -->
7188

7289
```python
73-
90+
class Solution:
91+
def getProbability(self, balls: List[int]) -> float:
92+
@cache
93+
def dfs(i: int, j: int, diff: int) -> float:
94+
if i >= k:
95+
return 1 if j == 0 and diff == 0 else 0
96+
if j < 0:
97+
return 0
98+
ans = 0
99+
for x in range(balls[i] + 1):
100+
y = 1 if x == balls[i] else (-1 if x == 0 else 0)
101+
ans += dfs(i + 1, j - x, diff + y) * comb(balls[i], x)
102+
return ans
103+
104+
n = sum(balls) >> 1
105+
k = len(balls)
106+
return dfs(0, n, 0) / comb(n << 1, n)
74107
```
75108

76109
### **Java**
77110

78111
<!-- 这里可写当前语言的特殊实现逻辑 -->
79112

80113
```java
114+
class Solution {
115+
private int n;
116+
private long[][] c;
117+
private int[] balls;
118+
private Map<List<Integer>, Long> f = new HashMap<>();
119+
120+
public double getProbability(int[] balls) {
121+
int mx = 0;
122+
for (int x : balls) {
123+
n += x;
124+
mx = Math.max(mx, x);
125+
}
126+
n >>= 1;
127+
this.balls = balls;
128+
int m = Math.max(mx, n << 1);
129+
c = new long[m + 1][m + 1];
130+
for (int i = 0; i <= m; ++i) {
131+
c[i][0] = 1;
132+
for (int j = 1; j <= i; ++j) {
133+
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
134+
}
135+
}
136+
return dfs(0, n, 0) * 1.0 / c[n << 1][n];
137+
}
138+
139+
private long dfs(int i, int j, int diff) {
140+
if (i >= balls.length) {
141+
return j == 0 && diff == 0 ? 1 : 0;
142+
}
143+
if (j < 0) {
144+
return 0;
145+
}
146+
List<Integer> key = List.of(i, j, diff);
147+
if (f.containsKey(key)) {
148+
return f.get(key);
149+
}
150+
long ans = 0;
151+
for (int x = 0; x <= balls[i]; ++x) {
152+
int y = x == balls[i] ? 1 : (x == 0 ? -1 : 0);
153+
ans += dfs(i + 1, j - x, diff + y) * c[balls[i]][x];
154+
}
155+
f.put(key, ans);
156+
return ans;
157+
}
158+
}
159+
```
160+
161+
### **C++**
162+
163+
```cpp
164+
class Solution {
165+
public:
166+
double getProbability(vector<int>& balls) {
167+
int n = accumulate(balls.begin(), balls.end(), 0) / 2;
168+
int mx = *max_element(balls.begin(), balls.end());
169+
int m = max(mx, n << 1);
170+
long long c[m + 1][m + 1];
171+
memset(c, 0, sizeof(c));
172+
for (int i = 0; i <= m; ++i) {
173+
c[i][0] = 1;
174+
for (int j = 1; j <= i; ++j) {
175+
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
176+
}
177+
}
178+
int k = balls.size();
179+
long long f[k][n + 1][k << 1 | 1];
180+
memset(f, -1, sizeof(f));
181+
function<long long(int, int, int)> dfs = [&](int i, int j, int diff) -> long long {
182+
if (i >= k) {
183+
return j == 0 && diff == k ? 1 : 0;
184+
}
185+
if (j < 0) {
186+
return 0;
187+
}
188+
if (f[i][j][diff] != -1) {
189+
return f[i][j][diff];
190+
}
191+
long long ans = 0;
192+
for (int x = 0; x <= balls[i]; ++x) {
193+
int y = x == balls[i] ? 1 : (x == 0 ? -1 : 0);
194+
ans += dfs(i + 1, j - x, diff + y) * c[balls[i]][x];
195+
}
196+
return f[i][j][diff] = ans;
197+
};
198+
return dfs(0, n, k) * 1.0 / c[n << 1][n];
199+
}
200+
};
201+
```
202+
203+
### **Go**
204+
205+
```go
206+
func getProbability(balls []int) float64 {
207+
n, mx := 0, 0
208+
for _, x := range balls {
209+
n += x
210+
mx = max(mx, x)
211+
}
212+
n >>= 1
213+
m := max(mx, n<<1)
214+
c := make([][]int, m+1)
215+
for i := range c {
216+
c[i] = make([]int, m+1)
217+
}
218+
for i := 0; i <= m; i++ {
219+
c[i][0] = 1
220+
for j := 1; j <= i; j++ {
221+
c[i][j] = c[i-1][j-1] + c[i-1][j]
222+
}
223+
}
224+
k := len(balls)
225+
f := make([][][]int, k)
226+
for i := range f {
227+
f[i] = make([][]int, n+1)
228+
for j := range f[i] {
229+
f[i][j] = make([]int, k<<1|1)
230+
for h := range f[i][j] {
231+
f[i][j][h] = -1
232+
}
233+
}
234+
}
235+
var dfs func(int, int, int) int
236+
dfs = func(i, j, diff int) int {
237+
if i >= k {
238+
if j == 0 && diff == k {
239+
return 1
240+
}
241+
return 0
242+
}
243+
if j < 0 {
244+
return 0
245+
}
246+
if f[i][j][diff] != -1 {
247+
return f[i][j][diff]
248+
}
249+
ans := 0
250+
for x := 0; x <= balls[i]; x++ {
251+
y := 1
252+
if x != balls[i] {
253+
if x == 0 {
254+
y = -1
255+
} else {
256+
y = 0
257+
}
258+
}
259+
ans += dfs(i+1, j-x, diff+y) * c[balls[i]][x]
260+
}
261+
f[i][j][diff] = ans
262+
return ans
263+
}
264+
return float64(dfs(0, n, k)) / float64(c[n<<1][n])
265+
}
266+
267+
func max(a, b int) int {
268+
if a > b {
269+
return a
270+
}
271+
return b
272+
}
273+
```
81274

275+
### **TypeScript**
276+
277+
```ts
278+
function getProbability(balls: number[]): number {
279+
const n = balls.reduce((a, b) => a + b, 0) >> 1;
280+
const mx = Math.max(...balls);
281+
const m = Math.max(mx, n << 1);
282+
const c: number[][] = Array(m + 1)
283+
.fill(0)
284+
.map(() => Array(m + 1).fill(0));
285+
for (let i = 0; i <= m; ++i) {
286+
c[i][0] = 1;
287+
for (let j = 1; j <= i; ++j) {
288+
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
289+
}
290+
}
291+
const k = balls.length;
292+
const f: number[][][] = Array(k)
293+
.fill(0)
294+
.map(() =>
295+
Array(n + 1)
296+
.fill(0)
297+
.map(() => Array((k << 1) | 1).fill(-1)),
298+
);
299+
const dfs = (i: number, j: number, diff: number): number => {
300+
if (i >= k) {
301+
return j === 0 && diff === k ? 1 : 0;
302+
}
303+
if (j < 0) {
304+
return 0;
305+
}
306+
if (f[i][j][diff] !== -1) {
307+
return f[i][j][diff];
308+
}
309+
let ans = 0;
310+
for (let x = 0; x <= balls[i]; ++x) {
311+
const y = x === balls[i] ? 1 : x === 0 ? -1 : 0;
312+
ans += dfs(i + 1, j - x, diff + y) * c[balls[i]][x];
313+
}
314+
return (f[i][j][diff] = ans);
315+
};
316+
return dfs(0, n, k) / c[n << 1][n];
317+
}
82318
```
83319

84320
### **...**

0 commit comments

Comments
 (0)