LeetCode 1864. 构成交替字符串需要的最小交换次数
题意
给一个二进制字符串s,请将其转化为一个交替字符串,返回转化所需的最小字符交换次数, 如果无法完成转化,返回-1。交替字符串的定义:相邻字符之间不存在相等情况的字符串。例如:“010”和“1010”是交替字符串,但“0100”不是。任意两个字符都可以进行交换,不必相邻 。
分析
1.对于二进制字符串,里面的组成元素只有‘0’和’1’,因此对于固定长度的二进制字符串只有
两种交替字符串状态:“010101…”和“101010…”
2.那么给定的二进制字符串也只能变成上面的两种交替字符串状态了,使用给定的二进制字符串分别
与上面的两种状态进行匹配,匹配出现的情况一共有4种:
给定字符串s:0 1 0 1
交替字符串a:0 1 1 0
第一种情况是两者都是0,则说明s在某个索引上的字符是和a相同的,不需要做任何操作。
第二种情况是两者都是1,则说明s在某个索引上的字符是和a相同的,不需要做任何操作。
第三种情况是s在某个索引上的字符是’1’,而a在对应的索引上的字符是’0’,两个字符不相同,因此s需要与它自身其他字符值为’0’的元素进行交换操作。
第四种情况是s在某个索引上的字符是’0’,而a在对应的索引上的字符是’1’,两个字符不相同,因此s需要与它自身其他字符值为’1’的元素进行交换操作。
因此,可以把第三种情况中的’1’与第四种情况中的’0’进行交换操作,这样第三种情况中的’1’就变成了’0’,而第四种情况的’0’就变成了’1’。也就是说,如果s的第三种情况的出现次数等于第四种情况的出现次数,那么s就可以通过交换字符操作变成交替字符串, 且是最小字符交换次数。
代码
c++
class Solution {
public:
//字符串a为交替字符串,字符串b为给定字符串
int solve(string a, string b) {
//x用于统计交替字符串某个索引为'0',而给定字符串对应索引为'1'的情况
//y用于统计交替字符串某个索引为'1',而给定字符串对应索引为'0'的情况
int x = 0, y = 0;
for (int i = 0; i < a.size(); i++) {
if (a[i] != b[i]) {
if (a[i] == '0') x++;
else y++;
}
}
//如果x不等于y,则说明给定字符串无法变成交替字符串
if (x != y) return INT_MAX;
return x;
}
int minSwaps(string s) {
int n = s.size();//取得给定字符串s的长度
string a(n, '0'), b(n, '0');//初始化两个字符串
for (int i = 0; i < n; i += 2) a[i] = '1';//"1010..."
for (int i = 1; i < n; i += 2) b[i] = '1';//"0101..."
int ans = min(solve(s, a), solve(s, b));
if (ans == INT_MAX) return -1;
return ans;
}
};
Java
class Solution {
int solve(char[] a, char[] b) {
int x = 0, y = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
if (a[i] == '0') x++;
else y++;
}
}
return x == y ? x : Integer.MAX_VALUE;
}
public int minSwaps(String s) {
int n = s.length();
char[] a = new char[n];
char[] b = new char[n];
for (int i = 0; i < n; i++) a[i] = '0';
for (int i = 0; i < n; i++) b[i] = '0';
for (int i = 0; i < n; i += 2) a[i] = '1';
for (int i = 1; i < n; i += 2) b[i] = '1';
int ans = Math.min(solve(s.toCharArray(), a), solve(s.toCharArray(), b));
return ans == Integer.MAX_VALUE ? -1 : ans;
}
}