「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」
前言
每日一题,轻松解题
每日一题为刷题系列 每日刷一题LeetCode题,并且对题目进行分析,分享思路。
正文
:构成交替字符串需要的最小交换次数
难度:中等
题目要求:
给你一个二进制字符串 s ,现需要将其转化为一个 交替字符串 。请你计算并返回转化所需的 最小 字符交换次数,如果无法完成转化,返回 -1 。
交替字符串 是指:相邻字符之间不存在相等情况的字符串。例如,字符串 "010" 和 "1010" 属于交替字符串,但 "0100" 不是。
任意两个字符都可以进行交换,不必相邻 。
分析题目:
一个二进制字符串,只包含数字0和1,给一串随机字符串,要使字符串没有相同的两个数字相邻就属于交替字符串,要获取最小次数的结果,如果本身就是交替字符串就为0
举个例子
输入: s = "111000"
输出: 1
解释: 交换位置 1 和 4:"111000" -> "101010" ,字符串变为交替字符串。
:解题
方法一
理清思路:
分析:
符合要求的交替字符串的形式只有两种:
1.形如 \texttt{"1010..."}"1010..." 的字符串,奇数位为 \texttt{0'}‘0’,偶数位为 \texttt{1'}‘1’;
2.形如 \texttt{"0101..."}"0101..." 的字符串,奇数位为 \texttt{1'}‘1’,偶数位为 \texttt{0'}‘0’。
二进制源字符串 s_1s 1和目标字符串 s_2s 2可以通过交换操作互相转化,当且仅当两个字符串中 \texttt{'0'}‘0’ 和 \texttt{'1'}‘1’ 的个数均相等。
假设 s_1s 1和 s_2s 2可以通过交换操作互相转化,且它们有 kk 个位置不同,那么最小的交换次数为 k/2k/2。
思路与算法
我们枚举两种交替字符串的形式,并根据 提示 22 判断 \texttt{'0'}‘0’ 和 \texttt{'1'}‘1’ 的个数是否相等。如果相等,我们可以计算出 ss 与上述目标字符串不同的位数 \texttt{diff}_1diff 1和 \texttt{diff}_2diff 2
。此时根据 提示 33,对应的最少交换次数即为 \texttt{diff}_1 / 2diff 1 /2 和 \texttt{diff}_2 / 2diff
2/2。最终,我们取两种情况的较小值作为答案返回;若两种情况均不满足,则返回 -1−1。
编辑代码:
class Solution {
public:
int minSwaps(string s) {
int n = s.size();
int n0 = count(s.begin(), s.end(), '0');
int n1 = count(s.begin(), s.end(), '1');
int res = INT_MAX;
// "1010..."
if (n1 == (n + 1) / 2 && n0 == n / 2){ // 不同字符个数相等
int diff1 = 0;
for (int i = 0; i < n; ++i){
if (s[i] - '0' == i % 2){ // 对应位数不同
++diff1;
}
}
res = min(res, diff1 / 2);
}
// "0101..."
if (n0 == (n + 1) / 2 && n1 == n / 2){ // 不同字符个数相等
int diff2 = 0;
for (int i = 0; i < n; ++i){
if (s[i] - '0' != i % 2){ // 对应位数不同
++diff2;
}
}
res = min(res, diff2 / 2);
}
if (res == INT_MAX){
return -1; // 不存在
}
else {
return res;
}
}
};
总结
无论做什么分析最重要,其中我们分析了题目,分析了解题思路,其实在分析完解题思路后,代码其实就是很简单的事情了,养成习惯,无论做什么之前,都要进行分析,这样有助于你更快更好的完成这件事。