携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
题目描述
给定一个特殊的二进制序列字符串str,你可以进行任意次数的操作,每次操作要选择str中两个连续的且非空的特殊字串,然后将他们交换,返回经过若干次操作后,str的字典序最大的一个操作结果。
对于特殊二进制序列定义:
- 序列中1和0的数量相等
- 每个序列的前缀码中1的个数都不小于0的个数。
例如110为特殊二进制序列,而100不是,因为其前缀码100的1数目小于0的数目。
例1:输入:str="1100110100" 输出:"1101001100"
解释:将str索引0 ~ 3的1100与索引4 ~ 9的110100进行交换后所得的字符串字典序最大。
原题地址:761. 特殊的二进制序列
解题思路
由特殊二进制序列的定义可知,一个特殊二进制序列的第一个数必定为1(因为前缀码1的数要不小于0的数,当前缀码取第一个数时,则第一个数必定为1),最后一个数必定为0(例如str长度为n,因为0和1的数相等,而前n-1个数1的个数大于0的个数,所以最后一个数必定为0才能保证全部的数中0和1数目相等)。
可以选择将特殊序列str中所有的子特殊序列找出,然后将多个连续的子特殊序列进行排序得到字典序最大的子特殊序列,然后继续进行排序,直至所有的子特殊序列都排序完成,所得的结果即为字典序最大的字符串。
实现代码
class Solution {
public:
string makeLargestSpecial(string s) {
// 如果当前子序列长度为2,则返回
if(s.size() == 2) return s;
// 记录当前特殊序列的所有子特殊序列
vector<string> strs;
int num = 0,ll = 0;
// 处理当前特殊序列
for(int i = 0;i < s.size();i++){
if(s[i] == '1') num++;
else if(--num == 0){
// 处理特殊序列中除首位1、0外的子特殊序列
strs.emplace_back("1"+makeLargestSpecial(s.substr(ll+1,i-ll-1))+"0");
ll = i+1;
}
}
// 将所有子特殊序列进行按字典序从大到小进行排序
sort(strs.begin(),strs.end(),greater<string>{});
string res = "";
// 将排序的结果进行拼接,结果即为当前特殊序列的字典序最大的字符串
for(auto &str:strs) res += str;
return res;
}
};