2022.10.17 总结
1.逐月 P5000
题意
有一个长度为 \(n\) 的 \(01\) 字符串,令 \(d\) 为 \(\min \{i - j\}\) \((s_i = 1, s_j = 1, j < i)\)。
现在需要将两个 \(0\) 改成 \(1\),请求出最大的 \(d\)。
思路
100 分
先来两个函数。
int Mind(string p){ // 最小间隔
string t = p;
int last = -1, mind = n + 1;
for (int i = 0; i < n; i++) {
if (t[i] == '1') {
if (last == -1) {
last = i;
} else {
mind = min(mind, i - last);
last = i;
}
}
}
return (mind == n + 1 ? -1 : mind);
}
int Maxd(string p){ // 最大间隔
string t = p;
int last = -1, maxd = -1;
for (int i = 0; i < n; i++) {
if (t[i] == '1') {
if (last == -1) {
last = i;
} else {
maxd = max(maxd, i - last);
last = i;
}
}
}
return maxd;
}
需要分类讨论两个 \(1\) 的位置。
- 最左边和最右边
int len1(){
string t = s;
if (t[0] == '1' || t[n - 1] == '1') {
return -1;
}
t[0] = t[n - 1] = '1';
return Mind(t);
}
- 最左边一个,中间一个
int len2(){
string t = s;
if (t[0] == '1') {
return -1;
}
t[0] = '1';
return min(Mind(t), Maxd(t) / 2);
}
- 最右边一个,中间一个
int len3(){
string t = s;
if (t[n - 1] == '1') {
return -1;
}
t[n - 1] = '1';
return min(Mind(t), Maxd(t) / 2);
}
- 最长区间 \(3\) 等分点
int len4(){
return min(Mind(s), Maxd(s) / 3);
}
- 最长区间等分点和次长区间等分点
int len5(){
int last = -1, d1 = 0, d2 = 0;
for (int i = 0; i < n; i++) {
if (s[i] == '1') {
if (last == -1) {
last = i;
} else {
if (i - last > d1) {
d2 = d1, d1 = i - last;
} else {
d2 = max(d2, i - last);
}
last = i;
}
}
}
return (!d2 ? -1 : min(Mind(s), d2 / 2));
}
时间复杂度
每个函数都是 \(O(n)\),总时间复杂度为 \(O(n)\)。
空间复杂度
长度为 \(n\) 的字符串,\(O(n)\)。