携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
题目描述
给定一个字符串s,s由字母及数字组成,要求对所给的字符串s进行重新排列,要求数字后必须跟字母且字母后必须跟数字。所给字符串能得到的结果可能有多个,返回其中的一个即可。
例1:输入:s="113aaa1d1" 输出:"1a1d1a1a3"
解释:可以看到的是所输出的结果符合字母后跟数字、数字后跟字母的要求,当然,字符串"3a1d1a1a1"、"1a1d1a3a1"等也符合要求。
例1:输入:s="113aaa11" 输出:""
解释:可以看到所给的例子中无法进行重新排列成符合要求的字符串。
原题地址:1417. 重新格式化字符串
解题思路
根据题意可以得到结论
- 如果字符串中数字个数和字母个数相差的个数大于1,则一定不存在符合要求的结果。
- 如果存在符合要求的结果,我们可以把个数相对多的类型放在偶数位,个数相对少的类型放在偶数位。一个字符串中偶数位中需要交换的字符的个数和奇数位需要交换的字符个数一定是相同的。比如"113aaa1d1",可以看到偶数位应该放数字,奇数位应该放字母。偶数位中索引4、奇数位中索引1时不符合要求的,将其交换可得"1a3a1a1d1",即得到符合要求的结果。
根据结论可知可以用两个变量分别维护偶数位、奇数位需要交换的位置信息,当偶数位某一位置所存放的数据类型不正确时,则去寻找奇数位中数据类型存放不正确的位置,将二者交换即可。
实现代码
class Solution {
public:
string reformat(string s) {
// 记录字符串中数字和字母各自的个数
int digit = 0,alpha = 0;
for(int i=0;i<s.size();i++)
if(isdigit(s[i])) digit++;
alpha=s.size() - digit;
// 如果数字比字母的差不小于或等于1 则无法按照要求重新格式化
if (abs(sum_digit - sum_alpha) > 1) return "";
// flag表示数字和字母多的是那个,如果数字比字母多,则flag为true
bool flag = digit > alpha;
// 寻找需要交换元素的位置
for (int i = 0, j = 1; i < s.size(); i += 2) {
// 如果当前偶数位不为个数多的那个类型
if (isdigit(s[i]) != flag) {
// 寻找需要奇数位不为个数少的那个类型,并与偶数位交换
while (isdigit(s[j]) != flag) {
j += 2;
}
swap(s[i], s[j]);
}
}
return s;
}
};