Skip to content

Commit 24d191c

Browse files
committed
feat: add solutions to lc problem: No.1655
No.1655.Distribute Repeating Integers
1 parent e43dd02 commit 24d191c

File tree

7 files changed

+671
-2
lines changed

7 files changed

+671
-2
lines changed

solution/1600-1699/1655.Distribute Repeating Integers/README.md

Lines changed: 239 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,260 @@
6060

6161
<!-- 这里可写通用的实现逻辑 -->
6262

63+
**方法一:状态压缩动态规划 + 子集枚举**
64+
65+
我们先统计数组 $nums$ 中每个数字出现的次数,记录在哈希表 $cnt$ 中,然后将哈希表中的值存入数组 $arr$ 中,我们记数组 $arr$ 的长度为 $n$。
66+
67+
注意到数组 $quantity$ 的长度不超过 $10$,因此,我们可以用一个二进制数表示 $quantity$ 中的一个子集,即数字 $j$ 表示 $quantity$ 中的一个子集,其中 $j$ 的二进制表示中的第 $i$ 位为 $1$ 表示 $quantity$ 中的第 $i$ 个数字被选中,为 $0$ 表示第 $i$ 个数字未被选中。
68+
69+
我们可以预处理出数组 $s$,其中 $s[j]$ 表示 $quantity$ 中子集 $j$ 中所有数字的和。
70+
71+
接下来,我们定义 $f[i][j]$ 表示数组 $arr[0,..i-1]$ 中的数字能否成功分配给 $quantity$ 中的子集 $j$,其中 $i$ 的取值范围为 $[0,..n-1]$,而 $j$ 的取值范围为 $[0,2^m-1]$,其中 $m$ 为 $quantity$ 的长度。
72+
73+
考虑 $f[i][j]$,如果子集 $j$ 中存在一个子集 $k$,使得 $s[k] \leq arr[i]$,并且 $f[i-1][j \oplus k]$ 为真,那么 $f[i][j]$ 为真,否则 $f[i][j]$ 为假。
74+
75+
答案为 $f[n-1][2^m-1]$。
76+
77+
时间复杂度 $O(n \times 3^m)$,空间复杂度 $O(n \times 2^m)$。其中 $n$ 是数组 $nums$ 中不同整数的个数;而 $m$ 是数组 $quantity$ 的长度。
78+
6379
<!-- tabs:start -->
6480

6581
### **Python3**
6682

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

6985
```python
70-
86+
class Solution:
87+
def canDistribute(self, nums: List[int], quantity: List[int]) -> bool:
88+
m = len(quantity)
89+
s = [0] * (1 << m)
90+
for i in range(1, 1 << m):
91+
for j in range(m):
92+
if i >> j & 1:
93+
s[i] = s[i ^ (1 << j)] + quantity[j]
94+
break
95+
cnt = Counter(nums)
96+
arr = list(cnt.values())
97+
n = len(arr)
98+
f = [[False] * (1 << m) for _ in range(n)]
99+
for i in range(n):
100+
f[i][0] = True
101+
for i, x in enumerate(arr):
102+
for j in range(1, 1 << m):
103+
if i and f[i - 1][j]:
104+
f[i][j] = True
105+
continue
106+
k = j
107+
while k:
108+
ok1 = j == k if i == 0 else f[i - 1][j ^ k]
109+
ok2 = s[k] <= x
110+
if ok1 and ok2:
111+
f[i][j] = True
112+
break
113+
k = (k - 1) & j
114+
return f[-1][-1]
71115
```
72116

73117
### **Java**
74118

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

77121
```java
122+
class Solution {
123+
public boolean canDistribute(int[] nums, int[] quantity) {
124+
int m = quantity.length;
125+
int[] s = new int[1 << m];
126+
for (int i = 1; i < 1 << m; ++i) {
127+
for (int j = 0; j < m; ++j) {
128+
if ((i >> j & 1) != 0) {
129+
s[i] = s[i ^ (1 << j)] + quantity[j];
130+
break;
131+
}
132+
}
133+
}
134+
Map<Integer, Integer> cnt = new HashMap<>(50);
135+
for (int x : nums) {
136+
cnt.merge(x, 1, Integer::sum);
137+
}
138+
int n = cnt.size();
139+
int[] arr = new int[n];
140+
int i = 0;
141+
for (int x : cnt.values()) {
142+
arr[i++] = x;
143+
}
144+
boolean[][] f = new boolean[n][1 << m];
145+
for (i = 0; i < n; ++i) {
146+
f[i][0] = true;
147+
}
148+
for (i = 0; i < n; ++i) {
149+
for (int j = 1; j < 1 << m; ++j) {
150+
if (i > 0 && f[i - 1][j]) {
151+
f[i][j] = true;
152+
continue;
153+
}
154+
for (int k = j; k > 0; k = (k - 1) & j) {
155+
boolean ok1 = i == 0 ? j == k : f[i - 1][j ^ k];
156+
boolean ok2 = s[k] <= arr[i];
157+
if (ok1 && ok2) {
158+
f[i][j] = true;
159+
break;
160+
}
161+
}
162+
}
163+
}
164+
return f[n - 1][(1 << m) - 1];
165+
}
166+
}
167+
```
168+
169+
### **C++**
170+
171+
```cpp
172+
class Solution {
173+
public:
174+
bool canDistribute(vector<int>& nums, vector<int>& quantity) {
175+
int m = quantity.size();
176+
int s[1 << m];
177+
memset(s, 0, sizeof(s));
178+
for (int i = 1; i < 1 << m; ++i) {
179+
for (int j = 0; j < m; ++j) {
180+
if (i >> j & 1) {
181+
s[i] = s[i ^ (1 << j)] + quantity[j];
182+
break;
183+
}
184+
}
185+
}
186+
unordered_map<int, int> cnt;
187+
for (int& x : nums) {
188+
++cnt[x];
189+
}
190+
int n = cnt.size();
191+
vector<int> arr;
192+
for (auto& [_, x] : cnt) {
193+
arr.push_back(x);
194+
}
195+
bool f[n][1 << m];
196+
memset(f, 0, sizeof(f));
197+
for (int i = 0; i < n; ++i) {
198+
f[i][0] = true;
199+
}
200+
for (int i = 0; i < n; ++i) {
201+
for (int j = 1; j < 1 << m; ++j) {
202+
if (i && f[i - 1][j]) {
203+
f[i][j] = true;
204+
continue;
205+
}
206+
for (int k = j; k; k = (k - 1) & j) {
207+
bool ok1 = i == 0 ? j == k : f[i - 1][j ^ k];
208+
bool ok2 = s[k] <= arr[i];
209+
if (ok1 && ok2) {
210+
f[i][j] = true;
211+
break;
212+
}
213+
}
214+
}
215+
}
216+
return f[n - 1][(1 << m) - 1];
217+
}
218+
};
219+
```
220+
221+
### **Go**
222+
223+
```go
224+
func canDistribute(nums []int, quantity []int) bool {
225+
m := len(quantity)
226+
s := make([]int, 1<<m)
227+
for i := 1; i < 1<<m; i++ {
228+
for j := 0; j < m; j++ {
229+
if i>>j&1 == 1 {
230+
s[i] = s[i^(1<<j)] + quantity[j]
231+
break
232+
}
233+
}
234+
}
235+
cnt := map[int]int{}
236+
for _, x := range nums {
237+
cnt[x]++
238+
}
239+
n := len(cnt)
240+
arr := make([]int, 0, n)
241+
for _, x := range cnt {
242+
arr = append(arr, x)
243+
}
244+
f := make([][]bool, n)
245+
for i := range f {
246+
f[i] = make([]bool, 1<<m)
247+
f[i][0] = true
248+
}
249+
for i := 0; i < n; i++ {
250+
for j := 0; j < 1<<m; j++ {
251+
if i > 0 && f[i-1][j] {
252+
f[i][j] = true
253+
continue
254+
}
255+
for k := j; k > 0; k = (k - 1) & j {
256+
ok1 := (i == 0 && j == k) || (i > 0 && f[i-1][j-k])
257+
ok2 := s[k] <= arr[i]
258+
if ok1 && ok2 {
259+
f[i][j] = true
260+
break
261+
}
262+
}
263+
}
264+
}
265+
return f[n-1][(1<<m)-1]
266+
}
267+
```
268+
269+
### **TypeScript**
78270

271+
```ts
272+
function canDistribute(nums: number[], quantity: number[]): boolean {
273+
const m = quantity.length;
274+
const s: number[] = new Array(1 << m).fill(0);
275+
for (let i = 1; i < 1 << m; ++i) {
276+
for (let j = 0; j < m; ++j) {
277+
if ((i >> j) & 1) {
278+
s[i] = s[i ^ (1 << j)] + quantity[j];
279+
break;
280+
}
281+
}
282+
}
283+
const cnt: Map<number, number> = new Map();
284+
for (const x of nums) {
285+
cnt.set(x, (cnt.get(x) || 0) + 1);
286+
}
287+
const n = cnt.size;
288+
const arr: number[] = [];
289+
for (const [_, v] of cnt) {
290+
arr.push(v);
291+
}
292+
const f: boolean[][] = new Array(n)
293+
.fill(false)
294+
.map(() => new Array(1 << m).fill(false));
295+
for (let i = 0; i < n; ++i) {
296+
f[i][0] = true;
297+
}
298+
for (let i = 0; i < n; ++i) {
299+
for (let j = 0; j < 1 << m; ++j) {
300+
if (i > 0 && f[i - 1][j]) {
301+
f[i][j] = true;
302+
continue;
303+
}
304+
for (let k = j; k > 0; k = (k - 1) & j) {
305+
const ok1: boolean =
306+
(i == 0 && j == k) || (i > 0 && f[i - 1][j ^ k]);
307+
const ok2: boolean = s[k] <= arr[i];
308+
if (ok1 && ok2) {
309+
f[i][j] = true;
310+
break;
311+
}
312+
}
313+
}
314+
}
315+
return f[n - 1][(1 << m) - 1];
316+
}
79317
```
80318

81319
### **...**

0 commit comments

Comments
 (0)