Skip to content

Commit 9c1d17f

Browse files
authored
feat: add solutions to lc problem: No.1879 (#1489)
No.1879.Minimum XOR Sum of Two Arrays
1 parent f87226f commit 9c1d17f

File tree

7 files changed

+759
-0
lines changed

7 files changed

+759
-0
lines changed

solution/1800-1899/1879.Minimum XOR Sum of Two Arrays/README.md

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,366 @@
5050

5151
<!-- 这里可写通用的实现逻辑 -->
5252

53+
**方法一:状态压缩动态规划**
54+
55+
我们注意到 $n \leq 14$,因此,我们可以考虑使用状态压缩动态规划的方法求解本题。
56+
57+
我们用一个长度为 $n$ 的二进制数表示当前的状态,第 $i$ 位为 $1$ 表示 $nums2[i]$ 已经被选择,为 $0$ 表示 $nums2[i]$ 还未被选择。
58+
59+
我们定义 $f[i][j]$ 表示 $nums1$ 的前 $i$ 个数中,选择了 $nums2$ 的 $i$ 个数,且当前所选数字的状态为 $j$ 时,数组 $nums1$ 和 $nums2$ 的异或值之和的最小值。初始时 $f[0][0]=0$,其余 $f[i][j]=+\infty$。
60+
61+
我们可以枚举 $nums1$ 的第 $i$ 个数 $x$,然后在 $[0,2^n)$ 的范围内枚举状态 $j$,转移方程为 $f[i][j]=\min(f[i][j],f[i-1][j\oplus 2^k]+(x\oplus nums2[k]))$,其中 $k$ 是 $j$ 的二进制表示中的某个 $1$ 所在的位置。
62+
63+
最后答案为 $f[n][2^n-1]$。
64+
65+
时间复杂度 $O(n^2 \times 2^n)$,空间复杂度 $O(n \times 2^n)$。其中 $n$ 是数组的长度。
66+
67+
我们注意到,状态 $f[i][j]$ 只与 $f[i-1][j\oplus 2^k]$ 有关,因此我们去掉第一维,将空间复杂度优化到 $O(2^n)$。
68+
69+
**方法二:状态压缩动态规划(枚举优化)**
70+
71+
我们也可以直接在 $[0, 2^n)$ 范围内枚举状态 $i$,假设 $i$ 的二进制表示中有 $k$ 个 $1$,那么当前枚举的就是 $nums1$ 的第 $k$ 个数,下标为 $k-1$。状态转移方程为 $f[i]=\min(f[i],f[i\oplus 2^j]+(nums1[k-1]\oplus nums2[j]))$,其中 $j$ 是 $i$ 的二进制表示中的某个 $1$ 所在的位置。
72+
73+
时间复杂度 $O(n \times 2^n)$,空间复杂度 $O(2^n)$。其中 $n$ 是数组的长度。
74+
5375
<!-- tabs:start -->
5476

5577
### **Python3**
5678

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

5981
```python
82+
class Solution:
83+
def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int:
84+
n = len(nums2)
85+
f = [[inf] * (1 << n) for _ in range(n + 1)]
86+
f[0][0] = 0
87+
for i, x in enumerate(nums1, 1):
88+
for j in range(1 << n):
89+
for k in range(n):
90+
if j >> k & 1:
91+
f[i][j] = min(f[i][j], f[i - 1][j ^ (1 << k)] + (x ^ nums2[k]))
92+
return f[-1][-1]
93+
```
6094

95+
```python
96+
class Solution:
97+
def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int:
98+
n = len(nums2)
99+
f = [inf] * (1 << n)
100+
f[0] = 0
101+
for x in nums1:
102+
for j in range((1 << n) - 1, -1, -1):
103+
for k in range(n):
104+
if j >> k & 1:
105+
f[j] = min(f[j], f[j ^ (1 << k)] + (x ^ nums2[k]))
106+
return f[-1]
107+
```
108+
109+
```python
110+
class Solution:
111+
def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int:
112+
n = len(nums2)
113+
f = [inf] * (1 << n)
114+
f[0] = 0
115+
for i in range(1, 1 << n):
116+
k = i.bit_count() - 1
117+
for j in range(n):
118+
if i >> j & 1:
119+
f[i] = min(f[i], f[i ^ (1 << j)] + (nums1[k] ^ nums2[j]))
120+
return f[-1]
61121
```
62122

63123
### **Java**
64124

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

67127
```java
128+
class Solution {
129+
public int minimumXORSum(int[] nums1, int[] nums2) {
130+
int n = nums1.length;
131+
int[][] f = new int[n + 1][1 << n];
132+
for (var g : f) {
133+
Arrays.fill(g, 1 << 30);
134+
}
135+
f[0][0] = 0;
136+
for (int i = 1; i <= n; ++i) {
137+
for (int j = 0; j < 1 << n; ++j) {
138+
for (int k = 0; k < n; ++k) {
139+
if ((j >> k & 1) == 1) {
140+
f[i][j] = Math.min(f[i][j], f[i - 1][j ^ (1 << k)] + (nums1[i - 1] ^ nums2[k]));
141+
}
142+
}
143+
}
144+
}
145+
return f[n][(1 << n) - 1];
146+
}
147+
}
148+
```
149+
150+
```java
151+
class Solution {
152+
public int minimumXORSum(int[] nums1, int[] nums2) {
153+
int n = nums1.length;
154+
int[] f = new int[1 << n];
155+
Arrays.fill(f, 1 << 30);
156+
f[0] = 0;
157+
for (int x : nums1) {
158+
for (int j = (1 << n) - 1; j >= 0; --j) {
159+
for (int k = 0; k < n; ++k) {
160+
if ((j >> k & 1) == 1) {
161+
f[j] = Math.min(f[j], f[j ^ (1 << k)] + (x ^ nums2[k]));
162+
}
163+
}
164+
}
165+
}
166+
return f[(1 << n) - 1];
167+
}
168+
}
169+
```
170+
171+
```java
172+
class Solution {
173+
public int minimumXORSum(int[] nums1, int[] nums2) {
174+
int n = nums1.length;
175+
int[] f = new int[1 << n];
176+
Arrays.fill(f, 1 << 30);
177+
f[0] = 0;
178+
for (int i = 0; i < 1 << n; ++i) {
179+
int k = Integer.bitCount(i) - 1;
180+
for (int j = 0; j < n; ++j) {
181+
if ((i >> j & 1) == 1) {
182+
f[i] = Math.min(f[i], f[i ^ (1 << j)] + (nums1[k] ^ nums2[j]));
183+
}
184+
}
185+
}
186+
return f[(1 << n) - 1];
187+
}
188+
}
189+
```
190+
191+
### **C++**
192+
193+
```cpp
194+
class Solution {
195+
public:
196+
int minimumXORSum(vector<int>& nums1, vector<int>& nums2) {
197+
int n = nums1.size();
198+
int f[n + 1][1 << n];
199+
memset(f, 0x3f, sizeof(f));
200+
f[0][0] = 0;
201+
for (int i = 1; i <= n; ++i) {
202+
for (int j = 0; j < 1 << n; ++j) {
203+
for (int k = 0; k < n; ++k) {
204+
if (j >> k & 1) {
205+
f[i][j] = min(f[i][j], f[i - 1][j ^ (1 << k)] + (nums1[i - 1] ^ nums2[k]));
206+
}
207+
}
208+
}
209+
}
210+
return f[n][(1 << n) - 1];
211+
}
212+
};
213+
```
214+
215+
```cpp
216+
class Solution {
217+
public:
218+
int minimumXORSum(vector<int>& nums1, vector<int>& nums2) {
219+
int n = nums1.size();
220+
int f[1 << n];
221+
memset(f, 0x3f, sizeof(f));
222+
f[0] = 0;
223+
for (int x : nums1) {
224+
for (int j = (1 << n) - 1; ~j; --j) {
225+
for (int k = 0; k < n; ++k) {
226+
if (j >> k & 1) {
227+
f[j] = min(f[j], f[j ^ (1 << k)] + (x ^ nums2[k]));
228+
}
229+
}
230+
}
231+
}
232+
return f[(1 << n) - 1];
233+
}
234+
};
235+
```
236+
237+
```cpp
238+
class Solution {
239+
public:
240+
int minimumXORSum(vector<int>& nums1, vector<int>& nums2) {
241+
int n = nums1.size();
242+
int f[1 << n];
243+
memset(f, 0x3f, sizeof(f));
244+
f[0] = 0;
245+
for (int i = 0; i < 1 << n; ++i) {
246+
int k = __builtin_popcount(i) - 1;
247+
for (int j = 0; j < n; ++j) {
248+
if (i >> j & 1) {
249+
f[i] = min(f[i], f[i ^ (1 << j)] + (nums1[k] ^ nums2[j]));
250+
}
251+
}
252+
}
253+
return f[(1 << n) - 1];
254+
}
255+
};
256+
```
257+
258+
### **Go**
259+
260+
```go
261+
func minimumXORSum(nums1 []int, nums2 []int) int {
262+
n := len(nums1)
263+
f := make([][]int, n+1)
264+
for i := range f {
265+
f[i] = make([]int, 1<<n)
266+
for j := range f[i] {
267+
f[i][j] = 1 << 30
268+
}
269+
}
270+
f[0][0] = 0
271+
for i := 1; i <= n; i++ {
272+
for j := 0; j < 1<<n; j++ {
273+
for k := 0; k < n; k++ {
274+
if j>>k&1 == 1 {
275+
f[i][j] = min(f[i][j], f[i-1][j^(1<<k)]+(nums1[i-1]^nums2[k]))
276+
}
277+
}
278+
}
279+
}
280+
return f[n][(1<<n)-1]
281+
}
282+
283+
func min(a, b int) int {
284+
if a < b {
285+
return a
286+
}
287+
return b
288+
}
289+
```
290+
291+
```go
292+
func minimumXORSum(nums1 []int, nums2 []int) int {
293+
n := len(nums1)
294+
f := make([]int, 1<<n)
295+
for i := range f {
296+
f[i] = 1 << 30
297+
}
298+
f[0] = 0
299+
for _, x := range nums1 {
300+
for j := (1 << n) - 1; j >= 0; j-- {
301+
for k := 0; k < n; k++ {
302+
if j>>k&1 == 1 {
303+
f[j] = min(f[j], f[j^(1<<k)]+(x^nums2[k]))
304+
}
305+
}
306+
}
307+
}
308+
return f[(1<<n)-1]
309+
}
310+
311+
func min(a, b int) int {
312+
if a < b {
313+
return a
314+
}
315+
return b
316+
}
317+
```
318+
319+
```go
320+
func minimumXORSum(nums1 []int, nums2 []int) int {
321+
n := len(nums1)
322+
f := make([]int, 1<<n)
323+
for i := range f {
324+
f[i] = 1 << 30
325+
}
326+
f[0] = 0
327+
for i := 0; i < 1<<n; i++ {
328+
k := bits.OnesCount(uint(i)) - 1
329+
for j := 0; j < n; j++ {
330+
if i>>j&1 == 1 {
331+
f[i] = min(f[i], f[i^1<<j]+(nums1[k]^nums2[j]))
332+
}
333+
}
334+
}
335+
return f[(1<<n)-1]
336+
}
337+
338+
func min(a, b int) int {
339+
if a < b {
340+
return a
341+
}
342+
return b
343+
}
344+
```
345+
346+
### **TypeScript**
347+
348+
```ts
349+
function minimumXORSum(nums1: number[], nums2: number[]): number {
350+
const n = nums1.length;
351+
const f: number[][] = Array(n + 1)
352+
.fill(0)
353+
.map(() => Array(1 << n).fill(1 << 30));
354+
f[0][0] = 0;
355+
for (let i = 1; i <= n; ++i) {
356+
for (let j = 0; j < 1 << n; ++j) {
357+
for (let k = 0; k < n; ++k) {
358+
if (((j >> k) & 1) === 1) {
359+
f[i][j] = Math.min(
360+
f[i][j],
361+
f[i - 1][j ^ (1 << k)] + (nums1[i - 1] ^ nums2[k]),
362+
);
363+
}
364+
}
365+
}
366+
}
367+
return f[n][(1 << n) - 1];
368+
}
369+
```
370+
371+
```ts
372+
function minimumXORSum(nums1: number[], nums2: number[]): number {
373+
const n = nums1.length;
374+
const f: number[] = Array(1 << n).fill(1 << 30);
375+
f[0] = 0;
376+
for (const x of nums1) {
377+
for (let j = (1 << n) - 1; ~j; --j) {
378+
for (let k = 0; k < n; ++k) {
379+
if (((j >> k) & 1) === 1) {
380+
f[j] = Math.min(f[j], f[j ^ (1 << k)] + (x ^ nums2[k]));
381+
}
382+
}
383+
}
384+
}
385+
return f[(1 << n) - 1];
386+
}
387+
```
388+
389+
```ts
390+
function minimumXORSum(nums1: number[], nums2: number[]): number {
391+
const n = nums1.length;
392+
const f: number[] = Array(1 << n).fill(1 << 30);
393+
f[0] = 0;
394+
for (let i = 0; i < 1 << n; ++i) {
395+
const k = bitCount(i) - 1;
396+
for (let j = 0; j < n; ++j) {
397+
if (((i >> j) & 1) === 1) {
398+
f[i] = Math.min(f[i], f[i ^ (1 << j)] + (nums1[k] ^ nums2[j]));
399+
}
400+
}
401+
}
402+
return f[(1 << n) - 1];
403+
}
68404

405+
function bitCount(i: number): number {
406+
i = i - ((i >>> 1) & 0x55555555);
407+
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
408+
i = (i + (i >>> 4)) & 0x0f0f0f0f;
409+
i = i + (i >>> 8);
410+
i = i + (i >>> 16);
411+
return i & 0x3f;
412+
}
69413
```
70414

71415
### **...**

0 commit comments

Comments
 (0)