65
65
66
66
<!-- solution:start -->
67
67
68
- ### 方法一
68
+ ### 方法一:计数
69
+
70
+ 我们先统计字符串 $\textit{s}$ 中字符 $0$ 和字符 $1$ 的个数,分别记为 $n_0$ 和 $n_1$。
71
+
72
+ 如果 $n_0$ 和 $n_1$ 的绝对值大于 $1$,那么无法构成交替字符串,返回 $-1$。
73
+
74
+ 如果 $n_0$ 和 $n_1$ 相等,那么我们可以分别计算将字符串转化为以 $0$ 开头和以 $1$ 开头的交替字符串所需要的交换次数,取最小值。
75
+
76
+ 如果 $n_0$ 和 $n_1$ 不相等,那么我们只需要计算将字符串转化为以字符个数较多的字符开头的交替字符串所需要的交换次数。
77
+
78
+ 问题转换为:计算字符串 $\textit{s}$ 转化为以字符 $c$ 开头的交替字符串所需要的交换次数。
79
+
80
+ 我们定义一个函数 $\text{calc}(c)$,表示将字符串 $\textit{s}$ 转化为以字符 $c$ 开头的交替字符串所需要的交换次数。我们遍历字符串 $\textit{s}$,对于每个位置 $i$,如果 $i$ 与 $c$ 的奇偶性不同,那么我们需要交换这个位置的字符,计数器 $+1$。由于每次交换都会使两个位置的字符变得相同,因此最终的交换次数为计数器的一半。
81
+
82
+ 时间复杂度 $O(n)$,其中 $n$ 是字符串 $\textit{s}$ 的长度。空间复杂度 $O(1)$。
69
83
70
84
<!-- tabs:start -->
71
85
@@ -74,60 +88,141 @@ tags:
74
88
``` python
75
89
class Solution :
76
90
def minSwaps (self , s : str ) -> int :
77
- s0n0 = s0n1 = s1n0 = s1n1 = 0
78
- for i in range (len (s)):
79
- if (i & 1 ) == 0 :
80
- if s[i] != ' 0' :
81
- s0n0 += 1
82
- else :
83
- s1n1 += 1
84
- else :
85
- if s[i] != ' 0' :
86
- s1n0 += 1
87
- else :
88
- s0n1 += 1
89
- if s0n0 != s0n1 and s1n0 != s1n1:
91
+ def calc (c : int ) -> int :
92
+ return sum ((c ^ i & 1 ) != x for i, x in enumerate (map (int , s))) // 2
93
+
94
+ n0 = s.count(" 0" )
95
+ n1 = len (s) - n0
96
+ if abs (n0 - n1) > 1 :
90
97
return - 1
91
- if s0n0 != s0n1:
92
- return s1n0
93
- if s1n0 != s1n1:
94
- return s0n0
95
- return min (s0n0, s1n0)
98
+ if n0 == n1:
99
+ return min (calc(0 ), calc(1 ))
100
+ return calc(0 if n0 > n1 else 1 )
96
101
```
97
102
98
103
#### Java
99
104
100
105
``` java
101
106
class Solution {
107
+ private char [] s;
108
+
102
109
public int minSwaps (String s ) {
103
- int s0n0 = 0 , s0n1 = 0 ;
104
- int s1n0 = 0 , s1n1 = 0 ;
105
- for (int i = 0 ; i < s. length(); ++ i) {
106
- if ((i & 1 ) == 0 ) {
107
- if (s. charAt(i) != ' 0' ) {
108
- s0n0 += 1 ;
109
- } else {
110
- s1n1 += 1 ;
111
- }
112
- } else {
113
- if (s. charAt(i) != ' 0' ) {
114
- s1n0 += 1 ;
115
- } else {
116
- s0n1 += 1 ;
117
- }
110
+ this . s = s. toCharArray();
111
+ int n1 = 0 ;
112
+ for (char c : this . s) {
113
+ n1 += (c - ' 0' );
114
+ }
115
+ int n0 = this . s. length - n1;
116
+ if (Math . abs(n0 - n1) > 1 ) {
117
+ return - 1 ;
118
+ }
119
+ if (n0 == n1) {
120
+ return Math . min(calc(0 ), calc(1 ));
121
+ }
122
+ return calc(n0 > n1 ? 0 : 1 );
123
+ }
124
+
125
+ private int calc (int c ) {
126
+ int cnt = 0 ;
127
+ for (int i = 0 ; i < s. length; ++ i) {
128
+ int x = s[i] - ' 0' ;
129
+ if ((i & 1 ^ c) != x) {
130
+ ++ cnt;
118
131
}
119
132
}
120
- if (s0n0 != s0n1 && s1n0 != s1n1) {
133
+ return cnt / 2 ;
134
+ }
135
+ }
136
+ ```
137
+
138
+ #### C++
139
+
140
+ ``` cpp
141
+ class Solution {
142
+ public:
143
+ int minSwaps(string s) {
144
+ int n0 = ranges::count(s, '0');
145
+ int n1 = s.size() - n0;
146
+ if (abs(n0 - n1) > 1) {
121
147
return -1;
122
148
}
123
- if (s0n0 != s0n1) {
124
- return s1n0;
149
+ auto calc = [ &] (int c) -> int {
150
+ int cnt = 0;
151
+ for (int i = 0; i < s.size(); ++i) {
152
+ int x = s[ i] - '0';
153
+ if ((i & 1 ^ c) != x) {
154
+ ++cnt;
155
+ }
156
+ }
157
+ return cnt / 2;
158
+ };
159
+ if (n0 == n1) {
160
+ return min(calc(0), calc(1));
125
161
}
126
- if (s1n0 != s1n1) {
127
- return s0n0;
162
+ return calc(n0 > n1 ? 0 : 1);
163
+ }
164
+ };
165
+ ```
166
+
167
+ #### Go
168
+
169
+ ```go
170
+ func minSwaps(s string) int {
171
+ n0 := strings.Count(s, "0")
172
+ n1 := len(s) - n0
173
+ if abs(n0-n1) > 1 {
174
+ return -1
175
+ }
176
+ calc := func(c int) int {
177
+ cnt := 0
178
+ for i, ch := range s {
179
+ x := int(ch - '0')
180
+ if i&1^c != x {
181
+ cnt++
182
+ }
183
+ }
184
+ return cnt / 2
185
+ }
186
+ if n0 == n1 {
187
+ return min(calc(0), calc(1))
188
+ }
189
+ if n0 > n1 {
190
+ return calc(0)
191
+ }
192
+ return calc(1)
193
+ }
194
+
195
+ func abs(x int) int {
196
+ if x < 0 {
197
+ return -x
198
+ }
199
+ return x
200
+ }
201
+ ```
202
+
203
+ #### TypeScript
204
+
205
+ ``` ts
206
+ function minSwaps(s : string ): number {
207
+ const n0 = (s .match (/ 0/ g ) || []).length ;
208
+ const n1 = s .length - n0 ;
209
+ if (Math .abs (n0 - n1 ) > 1 ) {
210
+ return - 1 ;
211
+ }
212
+ const calc = (c : number ): number => {
213
+ let cnt = 0 ;
214
+ for (let i = 0 ; i < s .length ; i ++ ) {
215
+ const x = + s [i ];
216
+ if (((i & 1 ) ^ c ) !== x ) {
217
+ cnt ++ ;
218
+ }
128
219
}
129
- return Math . min(s0n0, s1n0);
220
+ return Math .floor (cnt / 2 );
221
+ };
222
+ if (n0 === n1 ) {
223
+ return Math .min (calc (0 ), calc (1 ));
130
224
}
225
+ return calc (n0 > n1 ? 0 : 1 );
131
226
}
132
227
```
133
228
@@ -139,28 +234,25 @@ class Solution {
139
234
* @return {number}
140
235
*/
141
236
var minSwaps = function (s ) {
142
- let n = s .length ;
143
- let n1 = [... s].reduce ((a , c ) => parseInt (c) + a, 0 );
144
- let n0 = n - n1;
145
- let count = Infinity ;
146
- let half = n / 2 ;
147
- // 101、1010
148
- if (n1 == Math .ceil (half) && n0 == Math .floor (half)) {
149
- let cur = 0 ;
150
- for (let i = 0 ; i < n; i++ ) {
151
- if (i % 2 == 0 && s .charAt (i) != ' 1' ) cur++ ;
152
- }
153
- count = Math .min (count, cur);
237
+ const n0 = (s .match (/ 0/ g ) || []).length ;
238
+ const n1 = s .length - n0;
239
+ if (Math .abs (n0 - n1) > 1 ) {
240
+ return - 1 ;
154
241
}
155
- // 010、0101
156
- if (n0 == Math .ceil (half) && n1 == Math .floor (half)) {
157
- let cur = 0 ;
158
- for (let i = 0 ; i < n; i++ ) {
159
- if (i % 2 == 0 && s .charAt (i) != ' 0' ) cur++ ;
242
+ const calc = c => {
243
+ let cnt = 0 ;
244
+ for (let i = 0 ; i < s .length ; i++ ) {
245
+ const x = + s[i];
246
+ if (((i & 1 ) ^ c) !== x) {
247
+ cnt++ ;
248
+ }
160
249
}
161
- count = Math .min (count, cur);
250
+ return Math .floor (cnt / 2 );
251
+ };
252
+ if (n0 === n1) {
253
+ return Math .min (calc (0 ), calc (1 ));
162
254
}
163
- return count == Infinity ? - 1 : count ;
255
+ return calc (n0 > n1 ? 0 : 1 ) ;
164
256
};
165
257
```
166
258
0 commit comments