6565
6666<!-- solution:start -->
6767
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)$。
6983
7084<!-- tabs:start -->
7185
@@ -74,60 +88,141 @@ tags:
7488``` python
7589class Solution :
7690 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 :
9097 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 )
96101```
97102
98103#### Java
99104
100105``` java
101106class Solution {
107+ private char [] s;
108+
102109 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;
118131 }
119132 }
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) {
121147 return -1;
122148 }
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));
125161 }
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+ }
128219 }
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 ));
130224 }
225+ return calc (n0 > n1 ? 0 : 1 );
131226}
132227```
133228
@@ -139,28 +234,25 @@ class Solution {
139234 * @return {number}
140235 */
141236var 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 ;
154241 }
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+ }
160249 }
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 ));
162254 }
163- return count == Infinity ? - 1 : count ;
255+ return calc (n0 > n1 ? 0 : 1 ) ;
164256};
165257```
166258
0 commit comments