2 条题解
-
2
一、思路分析(超详细)
1. 题目核心:删除操作的本质拆解
题目允许多次删除任意一对相邻且不同的字符,目标是求删除后字符串的最小长度。首先明确该删除操作的核心特征:
- 操作本质:“消耗”两个不同字符(无论初始位置是否相邻)。即使两个不同字符不相邻,可通过删除中间字符让它们相邻,最终完成配对删除(例如字符串
abc,可先删ab剩c,或先删bc剩a)。 - 操作限制:无法删除相邻且相同的字符,因此“相同字符的出现次数”是决定最小长度的核心因素。
2. 核心规律推导
设字符串总长度为
len,统计每个字符的出现次数,记出现次数最多的字符次数为max_cnt,其余所有字符的总次数为other_cnt = len - max_cnt。根据两者的关系,分两种情况推导最小长度:- 情况1:若
max_cnt > other_cnt,说明出现次数最多的字符无法被其他字符完全配对消耗,最终剩余的字符数量为max_cnt - other_cnt(等价于2*max_cnt - len)。例如字符串abaca,a出现3次,b和c各出现1次,max_cnt=3,other_cnt=2,3>2,最终剩余3-2=1个字符。 - 情况2:若
max_cnt ≤ other_cnt,说明所有字符可尽可能两两配对(不同字符),最终剩余的长度由字符串总长度的奇偶性决定:总长度为偶数则剩余0,奇数则剩余1(即len % 2)。例如字符串aabc总长度4(偶数),a出现2次,b和c各1次,max_cnt=2,other_cnt=2,2≤2,最终剩余0;字符串abcdefg总长度7(奇数),每个字符各出现1次,max_cnt=1,other_cnt=6,1≤6,最终剩余1。
3. 解题步骤(O(n) 时间复杂度)
- 输入处理:读取测试用例组数
G,依次处理每组的字符串; - 字符计数:遍历字符串,统计每个小写字母的出现次数;
- 关键值计算:找到出现次数最多的字符的次数
max_cnt,并记录字符串总长度len; - 结果计算:根据
max_cnt与other_cnt的关系,按上述两种情况计算最小长度; - 输出结果:输出每组字符串对应的最小长度。
二、带详细注释的C++代码
#include<bits/stdc++.h> using namespace std; int main() { // 定义变量存储测试用例组数(题目中用G表示) int test_num; cin >> test_num; // 循环处理每组测试用例 while (test_num--) { // 存储当前待处理的字符串 string s; cin >> s; // 定义计数数组:char_count[0]对应'a',char_count[1]对应'b'…char_count[25]对应'z',初始值全为0 int char_count[26] = {0}; // 记录字符串的总长度 int len = s.size(); // 遍历字符串,统计每个字符的出现次数 for (char c : s) { // 将字符转换为0-25的索引(如'a'-'a'=0,'z'-'a'=25),对应计数数组位置+1 char_count[c - 'a']++; } // 找到所有字符中出现次数最多的那个次数max_cnt int max_cnt = 0; for (int i = 0; i < 26; i++) { max_cnt = max(max_cnt, char_count[i]); } // 计算删除操作后能得到的最小长度 int min_length; if (max_cnt > len - max_cnt) { // 情况1:最多的字符数超过其他字符总和,剩余数量为2*max_cnt - len min_length = 2 * max_cnt - len; } else { // 情况2:最多的字符数不超过其他字符总和,剩余长度为总长度的奇偶性(偶数0,奇数1) min_length = len % 2; } // 输出当前字符串的最小长度 cout << min_length << endl; } return 0; }三、代码关键细节补充
1. 核心逻辑优化说明
- 计数数组设计:仅使用长度为26的数组
char_count,精准对应26个小写字母,无冗余空间; - 最大次数查找:直接遍历计数数组(仅26次循环),相比排序操作(如
sort)更高效,避免了排序带来的额外时间开销; - 数据类型选择:全程使用
int类型即可满足需求,因为字符串长度不超过10000,字符出现次数也不会超过该值,不存在整数溢出风险,无需额外定义long long。
2. 样例验证(文字版)
逐一验证题目给出的样例输入,确保逻辑正确性:
- 样例输入
aabc:字符串长度4,a出现2次,b和c各出现1次。max_cnt=2,other_cnt=2,满足max_cnt ≤ other_cnt,最小长度为4%2=0,与样例输出一致; - 样例输入
abaca:字符串长度5,a出现3次,b和c各出现1次。max_cnt=3,other_cnt=2,满足max_cnt > other_cnt,最小长度为2*3-5=1,与样例输出一致; - 样例输入
avbvvcvvvd:字符串长度10,v出现6次,a、b、c、d各出现1次。max_cnt=6,other_cnt=4,满足max_cnt > other_cnt,最小长度为2*6-10=2,与样例输出一致; - 样例输入
abcdefg:字符串长度7,每个字符各出现1次。max_cnt=1,other_cnt=6,满足max_cnt ≤ other_cnt,最小长度为7%2=1,与样例输出一致; - 样例输入
dabbb:字符串长度5,b出现3次,d和a各出现1次。max_cnt=3,other_cnt=2,满足max_cnt > other_cnt,最小长度为2*3-5=1,与样例输出一致。
3. 边界情况验证(文字版)
针对特殊边界场景验证逻辑正确性:
- 全相同字符场景(如
aaaaa):字符串长度5,a出现5次,max_cnt=5,other_cnt=0,满足max_cnt > other_cnt,最小长度为2*5-5=5,符合预期(无法删除任何字符); - 长度为1的字符串(如
a):字符串长度1,a出现1次,max_cnt=1,other_cnt=0,满足max_cnt > other_cnt,最小长度为2*1-1=1,符合预期(无字符可删除); - 长度为2且字符不同的字符串(如
ab):字符串长度2,a和b各出现1次,max_cnt=1,other_cnt=1,满足max_cnt ≤ other_cnt,最小长度为2%2=0,符合预期(可删除这对不同字符)。
4. 时间与空间复杂度分析
- 时间复杂度:每组测试用例的操作包括遍历字符串统计字符(O(n),n为字符串长度)、遍历计数数组找最大次数(O(26)),总时间复杂度为
O(G*n)。其中G≤5,n≤10000,该复杂度完全满足题目要求,运行效率极高; - 空间复杂度:仅使用固定大小的计数数组(26个int)和存储字符串的空间,空间复杂度为
O(n)(主要由字符串存储占用),无额外冗余空间开销。
- 操作本质:“消耗”两个不同字符(无论初始位置是否相邻)。即使两个不同字符不相邻,可通过删除中间字符让它们相邻,最终完成配对删除(例如字符串
信息
- ID
- 4006
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 78
- 已通过
- 26
- 上传者