Skip to content

Commit 200907b

Browse files
committed
feat: add solutions to lc problem: No.1787
No.1787.Make the XOR of All Segments Equal to Zero
1 parent 2075416 commit 200907b

File tree

7 files changed

+406
-3
lines changed

7 files changed

+406
-3
lines changed

solution/1700-1799/1784.Check if Binary String Has at Most One Segment of Ones/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@
4646

4747
注意到字符串 $s$ 不含前导零,说明 $s$ 以 '1' 开头。
4848

49-
若字符串 $s$ 存在 "01" 串,那么 $s$ 就变成形如 "1...01..." 的字符串,此时 $s$ 出现了至少两个连续的 '1' 片段,不满足题意,返回 `false`
49+
若字符串 $s$ 存在 "01" 串,那么 $s$ 就是形如 "1...01..." 的字符串,此时 $s$ 出现了至少两个连续的 '1' 片段,不满足题意,返回 `false`
5050

5151
若字符串 $s$ 不存在 "01" 串,那么 $s$ 只能是形如 "1..1000..." 的字符串,此时 $s$ 只有一个连续的 '1' 片段,满足题意,返回 `true`
5252

5353
因此,只需要判断字符串 $s$ 是否存在 "01" 串即可。
5454

55+
时间复杂度 $O(n)$。其中 $n$ 为字符串 $s$ 的长度。
56+
5557
<!-- tabs:start -->
5658

5759
### **Python3**

solution/1700-1799/1787.Make the XOR of All Segments Equal to Zero/README.md

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,177 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

51+
**方法一:动态规划**
52+
53+
注意到数组 `nums` 在修改之后,任意长度为 $k$ 的区间异或结果都等于 $0$,那么对于任意的 $i$,都有:
54+
55+
$$
56+
nums[i] \oplus nums[i+1] \oplus ... \oplus nums[i+k-1] = 0
57+
$$
58+
59+
以及
60+
61+
$$
62+
nums[i+1] \oplus nums[i+2] \oplus ... \oplus nums[i+k] = 0
63+
$$
64+
65+
结合上面两个等式以及异或运算的性质,可以得到 $nums[i] \oplus nums[i+k] = 0$,即 $nums[i]=nums[i+k]$,我们发现,修改后的数组 `nums` 中的元素是以周期为 $k$ 的循环,对模 $k$ 同余的一组数必然只能取固定值,同时需要满足前 $k$ 个数异或结果为 $0$。
66+
67+
我们先对每一组 $i$ 进行计数,每一组的元素个数为 $size[i]$,每一组值为 $v$ 的元素个数为 $cnt[i][v]$。
68+
69+
接下来,我们可以用动态规划来求解。设 $f[i][j]$ 表示前 $i+1$ 组异或和为 $j$ 的最小修改次数。由于每一组的值只与前一组的值有关,因此我们可以用滚动数组优化空间复杂度。
70+
71+
重新定义 $f[j]$ 表示处理到当前组,且异或和为 $j$ 的最小修改次数。
72+
73+
状态转移时,有两种选择:一是将当前组的数全部都修改为同一个值,那么我们可以选择上一个代价最小的那个,加上这一组的元素个数 $size[i]$,此时的代价为 $\min{f[0..n]} + size[i]$;二是将当前组的数全部修改为当前组的某个值 $j$,枚举 $j$ 以及当前组的元素 $v$,那么前面的代价为 $f[j \oplus v]$,此时的代价为 $f[j \oplus v] + size[i] - cnt[i][v]$。取最小值即可。
74+
75+
最终答案为 $f[0]$。
76+
77+
时间复杂度 $O(2^{C}\times k + n)$。其中 $n$ 是数组 `nums` 的长度,而 $C$ 为 `nums` 中元素二进制表示的最大位数,本题中 $C=10$。
78+
5179
<!-- tabs:start -->
5280

5381
### **Python3**
5482

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

5785
```python
58-
86+
class Solution:
87+
def minChanges(self, nums: List[int], k: int) -> int:
88+
n = 1 << 10
89+
cnt = [Counter() for _ in range(k)]
90+
size = [0] * k
91+
for i, v in enumerate(nums):
92+
cnt[i % k][v] += 1
93+
size[i % k] += 1
94+
f = [inf] * n
95+
f[0] = 0
96+
for i in range(k):
97+
g = [min(f) + size[i]] * n
98+
for j in range(n):
99+
for v, c in cnt[i].items():
100+
g[j] = min(g[j], f[j ^ v] + size[i] - c)
101+
f = g
102+
return f[0]
59103
```
60104

61105
### **Java**
62106

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

65109
```java
110+
class Solution {
111+
public int minChanges(int[] nums, int k) {
112+
int n = 1 << 10;
113+
Map<Integer, Integer>[] cnt = new Map[k];
114+
int[] size = new int[k];
115+
for (int i = 0; i < k; ++i) {
116+
cnt[i] = new HashMap<>();
117+
}
118+
for (int i = 0; i < nums.length; ++i) {
119+
cnt[i % k].put(nums[i], cnt[i % k].getOrDefault(nums[i], 0) + 1);
120+
size[i % k]++;
121+
}
122+
int[] f = new int[n];
123+
Arrays.fill(f, 0x3f3f3f3f);
124+
f[0] = 0;
125+
for (int i = 0; i < k; ++i) {
126+
int[] g = new int[n];
127+
Arrays.fill(g, min(f) + size[i]);
128+
for (int j = 0; j < n; ++j) {
129+
for (var e : cnt[i].entrySet()) {
130+
int v = e.getKey(), c = e.getValue();
131+
g[j] = Math.min(g[j], f[j ^ v] + size[i] - c);
132+
}
133+
}
134+
f = g;
135+
}
136+
return f[0];
137+
}
138+
139+
private int min(int[] arr) {
140+
int mi = arr[0];
141+
for (int v : arr) {
142+
mi = Math.min(mi, v);
143+
}
144+
return mi;
145+
}
146+
}
147+
```
148+
149+
### **C++**
150+
151+
```cpp
152+
class Solution {
153+
public:
154+
int minChanges(vector<int>& nums, int k) {
155+
int n = 1 << 10;
156+
vector<unordered_map<int, int>> cnt(k);
157+
vector<int> size(k);
158+
for (int i = 0; i < nums.size(); ++i) {
159+
cnt[i % k][nums[i]]++;
160+
size[i % k]++;
161+
}
162+
vector<int> f(n, 0x3f3f3f3f);
163+
f[0] = 0;
164+
for (int i = 0; i < k; ++i) {
165+
int mi = *min_element(f.begin(), f.end());
166+
vector<int> g(n, mi + size[i]);
167+
for (int j = 0; j < n; ++j) {
168+
for (auto& [v, c] : cnt[i]) {
169+
g[j] = min(g[j], f[j ^ v] + size[i] - c);
170+
}
171+
}
172+
f = move(g);
173+
}
174+
return f[0];
175+
}
176+
};
177+
```
66178
179+
### **Go**
180+
181+
```go
182+
func minChanges(nums []int, k int) int {
183+
n := 1 << 10
184+
cnt := make([]map[int]int, k)
185+
for i := range cnt {
186+
cnt[i] = map[int]int{}
187+
}
188+
size := make([]int, k)
189+
for i, v := range nums {
190+
cnt[i%k][v]++
191+
size[i%k]++
192+
}
193+
f := make([]int, n)
194+
for i := 1; i < n; i++ {
195+
f[i] = 0x3f3f3f3f
196+
}
197+
for i, sz := range size {
198+
g := make([]int, n)
199+
x := min(f...) + sz
200+
for i := range g {
201+
g[i] = x
202+
}
203+
for j := 0; j < n; j++ {
204+
for v, c := range cnt[i] {
205+
g[j] = min(g[j], f[j^v]+sz-c)
206+
}
207+
}
208+
f = g
209+
}
210+
return f[0]
211+
}
212+
213+
func min(a ...int) int {
214+
mi := a[0]
215+
for _, v := range a {
216+
if mi > v {
217+
mi = v
218+
}
219+
}
220+
return mi
221+
}
67222
```
68223

69224
### **...**

solution/1700-1799/1787.Make the XOR of All Segments Equal to Zero/README_EN.md

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,140 @@
4747
### **Python3**
4848

4949
```python
50-
50+
class Solution:
51+
def minChanges(self, nums: List[int], k: int) -> int:
52+
n = 1 << 10
53+
cnt = [Counter() for _ in range(k)]
54+
size = [0] * k
55+
for i, v in enumerate(nums):
56+
cnt[i % k][v] += 1
57+
size[i % k] += 1
58+
f = [inf] * n
59+
f[0] = 0
60+
for i in range(k):
61+
g = [min(f) + size[i]] * n
62+
for j in range(n):
63+
for v, c in cnt[i].items():
64+
g[j] = min(g[j], f[j ^ v] + size[i] - c)
65+
f = g
66+
return f[0]
5167
```
5268

5369
### **Java**
5470

5571
```java
72+
class Solution {
73+
public int minChanges(int[] nums, int k) {
74+
int n = 1 << 10;
75+
Map<Integer, Integer>[] cnt = new Map[k];
76+
int[] size = new int[k];
77+
for (int i = 0; i < k; ++i) {
78+
cnt[i] = new HashMap<>();
79+
}
80+
for (int i = 0; i < nums.length; ++i) {
81+
cnt[i % k].put(nums[i], cnt[i % k].getOrDefault(nums[i], 0) + 1);
82+
size[i % k]++;
83+
}
84+
int[] f = new int[n];
85+
Arrays.fill(f, 0x3f3f3f3f);
86+
f[0] = 0;
87+
for (int i = 0; i < k; ++i) {
88+
int[] g = new int[n];
89+
Arrays.fill(g, min(f) + size[i]);
90+
for (int j = 0; j < n; ++j) {
91+
for (var e : cnt[i].entrySet()) {
92+
int v = e.getKey(), c = e.getValue();
93+
g[j] = Math.min(g[j], f[j ^ v] + size[i] - c);
94+
}
95+
}
96+
f = g;
97+
}
98+
return f[0];
99+
}
100+
101+
private int min(int[] arr) {
102+
int mi = arr[0];
103+
for (int v : arr) {
104+
mi = Math.min(mi, v);
105+
}
106+
return mi;
107+
}
108+
}
109+
```
110+
111+
### **C++**
112+
113+
```cpp
114+
class Solution {
115+
public:
116+
int minChanges(vector<int>& nums, int k) {
117+
int n = 1 << 10;
118+
vector<unordered_map<int, int>> cnt(k);
119+
vector<int> size(k);
120+
for (int i = 0; i < nums.size(); ++i) {
121+
cnt[i % k][nums[i]]++;
122+
size[i % k]++;
123+
}
124+
vector<int> f(n, 0x3f3f3f3f);
125+
f[0] = 0;
126+
for (int i = 0; i < k; ++i) {
127+
int mi = *min_element(f.begin(), f.end());
128+
vector<int> g(n, mi + size[i]);
129+
for (int j = 0; j < n; ++j) {
130+
for (auto& [v, c] : cnt[i]) {
131+
g[j] = min(g[j], f[j ^ v] + size[i] - c);
132+
}
133+
}
134+
f = move(g);
135+
}
136+
return f[0];
137+
}
138+
};
139+
```
56140
141+
### **Go**
142+
143+
```go
144+
func minChanges(nums []int, k int) int {
145+
n := 1 << 10
146+
cnt := make([]map[int]int, k)
147+
for i := range cnt {
148+
cnt[i] = map[int]int{}
149+
}
150+
size := make([]int, k)
151+
for i, v := range nums {
152+
cnt[i%k][v]++
153+
size[i%k]++
154+
}
155+
f := make([]int, n)
156+
for i := 1; i < n; i++ {
157+
f[i] = 0x3f3f3f3f
158+
}
159+
for i, sz := range size {
160+
g := make([]int, n)
161+
x := min(f...) + sz
162+
for i := range g {
163+
g[i] = x
164+
}
165+
for j := 0; j < n; j++ {
166+
for v, c := range cnt[i] {
167+
g[j] = min(g[j], f[j^v]+sz-c)
168+
}
169+
}
170+
f = g
171+
}
172+
return f[0]
173+
}
174+
175+
func min(a ...int) int {
176+
mi := a[0]
177+
for _, v := range a {
178+
if mi > v {
179+
mi = v
180+
}
181+
}
182+
return mi
183+
}
57184
```
58185

59186
### **...**
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Solution {
2+
public:
3+
int minChanges(vector<int>& nums, int k) {
4+
int n = 1 << 10;
5+
vector<unordered_map<int, int>> cnt(k);
6+
vector<int> size(k);
7+
for (int i = 0; i < nums.size(); ++i) {
8+
cnt[i % k][nums[i]]++;
9+
size[i % k]++;
10+
}
11+
vector<int> f(n, 0x3f3f3f3f);
12+
f[0] = 0;
13+
for (int i = 0; i < k; ++i) {
14+
int mi = *min_element(f.begin(), f.end());
15+
vector<int> g(n, mi + size[i]);
16+
for (int j = 0; j < n; ++j) {
17+
for (auto& [v, c] : cnt[i]) {
18+
g[j] = min(g[j], f[j ^ v] + size[i] - c);
19+
}
20+
}
21+
f = move(g);
22+
}
23+
return f[0];
24+
}
25+
};

0 commit comments

Comments
 (0)