给定一个长度为
n
n
n 的
01
01
01 字符串,
n
n
n 为偶数。
问至少要修改多少个字符,可以使得字符串被拆分成多个子段,每一个子段都是
0
0
0 或者都是
1
1
1 ,且长度都是偶数。
在最少修改次数的条件下,子段的最少数量是多少。
本题需要拆分思考。
首先考虑第
n
n
n 个字符,其必然要和第
n
−
1
n-1
n−1 个字符相同。
所以当这两个字符相同后,考虑第
n
−
2
n-2
n−2 个字符,必然要和第
n
−
3
n-3
n−3 个字符相同。以此类推,第
i
i
i 个字符要和第
i
+
1
i+1
i+1 个字符相同,
i
i
i 为奇数。
所以最少操作次数是,将所有第 i i i 个字符和第 i + 1 i+1 i+1 个字符不相同的 ( i , i + 1 ) (i,i+1) (i,i+1) 要进行修改,所以这就是最小修改次数。
而最少子段数量,则必然是考虑第 i i i 个字符和第 i + 1 i+1 i+1 个字符不相同的 ( i , i + 1 ) (i,i+1) (i,i+1) 这些配对应该修改成什么,应该和靠近其最近的一个第 j j j 个字符和第 j + 1 j+1 j+1 个字符相同的 ( j , j + 1 ) (j,j+1) (j,j+1) 保持一致。
时间复杂度: O ( n ) O(n) O(n)
#include
using namespace std;
void solve() {
int n;
string s;
cin >> n >> s;
vector<int> vec;
int ans1 = 0;
for (int i = 0; i < n; i += 2) {
if (s[i] == s[i + 1]) {
vec.push_back(s[i] - '0');
} else {
ans1 += 1;
}
}
int ans2 = 1;
// 考虑这些新的需要分成多少段
for (int i = 1; i < vec.size(); ++i) {
if (vec[i] != vec[i - 1]) {
ans2 += 1;
}
}
cout << ans1 << " " << ans2 << "\n";
}
int main()
{
int T;
cin >> T;
while (T--) solve();
return 0;
}