2026-04-01:等量移除后的字符串最小长度。用go语言,你会得到一个只含字符 a 和 b 的字符串 s。
你可以进行任意次操作:
-
选择字符串中的某一段连续的子串并把它删掉。
-
这个被删掉的子串要求满足:其中 a 的数量 = b 的数量。
-
删除后,原来子串两侧的剩余部分会直接拼接起来(中间不留空隙)。
问:经过任意次这样的删除操作之后,字符串最终可能达到的最短长度是多少(返回这个最小值)。
1 <= s.length <= 100000。
s[i] 是 'a' 或 'b'。
输入: s = "aaaa"。
输出: 4。
解释:
字符串 "aaaa" 中每个子字符串都仅包含 'a',无法移除任何部分,因此最小长度仍为 4。
题目来自力扣3746。
大体步骤如下:
第一步:理解题目核心规则
我们的操作规则:只能删除连续的、a的数量 = b的数量的子串,可操作任意次,求最终能得到的字符串最小长度。
字符串只有 a 和 b 两种字符,这是解题的关键前提。
第二步:分析删除操作的本质
- 每次删除的子串,都满足:a的个数 = b的个数 → 这意味着删除操作不会改变整个字符串中 a 和 b 数量的差值。 举例:原字符串有3个a、1个b,删除1个a+1个b的子串后,剩余2个a、0个b,差值始终是2。
- 我们可以无限次删除,最终剩下的字符串,一定无法再找到任何满足条件的子串(否则还能继续删)。
第三步:推导最终剩余字符串的特征
因为最终字符串无法删除任何子串,所以:
- 它里面只有一种字符(全a 或 全b)。 原因:如果同时有a和b,就一定能找到连续的、a和b数量相等的子串,还能继续删除,和“最终状态”矛盾。
第四步:计算最终最小长度
- 统计原字符串中a的总数量(记为countA)、b的总数量(记为countB);
- 最终只能剩下全a 或 全b,能留下的最小长度,就是两种字符数量的差值;
- 数学表达:最小长度 = |countA - countB|(绝对值,保证结果非负)。
第五步:代入示例验证
输入:s = "aaaa"
- 统计:countA = 4,countB = 0;
- 计算差值:|4 - 0| = 4;
- 结论:最小长度为4,和题目输出一致。
补充通用示例验证
- 输入:
ab→ countA=1,countB=1 → |1-1|=0(可以直接删除整个字符串,最终长度为0); - 输入:
aab→ countA=2,countB=1 → |2-1|=1(最终剩1个字符); - 输入:
abbaa→ countA=3,countB=2 → |3-2|=1(最终剩1个字符)。
时间复杂度与额外空间复杂度
1. 总时间复杂度
核心操作只有两步:统计字符a的数量、计算长度和差值。
- 统计a的数量需要遍历整个字符串一次,时间复杂度为 O(n)(n为字符串长度);
- 其他计算都是常数时间操作 O(1);
- 总时间复杂度:O(n)。
2. 总额外空间复杂度
- 代码中只使用了几个临时变量(存储a的数量、字符串长度、计算结果等);
- 没有创建与输入规模n相关的数组、集合等数据结构;
- 总额外空间复杂度:O(1)(常数级空间)。
总结
- 解题核心:删除操作不改变a和b的数量差,最终只能剩余单一字符,长度为两者数量的绝对值差;
- 时间复杂度:O(n),能高效处理题目要求的最大长度100000;
- 额外空间复杂度:O(1),无额外内存消耗。
Go完整代码如下:
package main
import (
"fmt"
"strings"
)
func minLengthAfterRemovals(s string) int {
k := strings.Count(s, "a")
return abs(k*2 - len(s))
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func main() {
s := "aaaa"
result := minLengthAfterRemovals(s)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def min_length_after_removals(s: str) -> int:
k = s.count('a')
return abs(k * 2 - len(s))
def main():
s = "aaaa"
result = min_length_after_removals(s)
print(result)
if __name__ == "__main__":
main()
C++完整代码如下:
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
int minLengthAfterRemovals(const std::string& s) {
int k = std::count(s.begin(), s.end(), 'a');
return std::abs(k * 2 - static_cast<int>(s.length()));
}
int main() {
std::string s = "aaaa";
int result = minLengthAfterRemovals(s);
std::cout << result << std::endl;
return 0;
}