字典序是指从前到后比较两个字符串的大小。首先比较第一个字符,如果不同则第1个字符较小的字符串更小,如果相同则比较第2个字符……如此继续,来比较整个字符串的大小
给定长度为N的字符串S,要构造一个长度为 N 的字符串 T。起初 ,T 是一个空串,随后反复进行下列任意操作,
-
从 S 的头部删除一个字符,加到 T 的尾部。
-
从 S 的尾部删除一个字符,加到 T 的尾部。
目标是构造字典序最小的字符串 T。
限制条件:
1 <= N <= 2000
输入:
N = 6
S = “ACDBCB”
输出:
ABCBCD
思路:
从字典序的性质来看,无论T的末尾有多大,只要前面部分的较小就可以。
贪心算法:不断取S的开头和末尾中较小的一个字符放到T的末尾,如果S的开头和末尾的字符相同时,为了能够尽早使用更小的字符,还要比较下一个字符的大小;如果下一个字符还相同,就继续比较
为什么还要比较下一个字符的大小呢?
比如说,S = “CDBC”,如果我们取开头的C,最终得到的结果是CCBD;如果我们取末尾的C,最终得到的结果是CBCD;很明显后面的小一点。 所以为了尽早取到更小的字符,要选取下一个字符更小的那边
按照思路一步步写的伪代码,有点冗余
String S,T;
int left,right;
while(left <= right){
if(S[left] < S[right]){
T += S[left++];
}else if(S[left] > S[right]){
T += S[right--];
}else (S[left] == S[right]){
int i = 1;
bool left = false;
while(left+i < right-i){
if(S[left + i] < S[right - i]){
left = true;
break;
}else if(S[i] > S[j]){
left = false;
break;
}else{
i++;
}
if(left){
T += S[left++];
else{
T += S[right--];
}
}
修改后的代码:
#include<iostream>
#include<cstring>
using namespace std;
int main(){
int N;
string S,T;
cin >> N;
cin >> S;
int left = 0,right = N - 1;
while(left <= right){
bool isLeft = false;//标记左边是否小于右边
for(int i = 0;left + i <= right; i++){//如果两边一样就继续循环,否则跳出
if(S[left + i] < S[right - i]){
isLeft = true;
break;
}else if(S[left + i] > S[right - i]){
isLeft = false;
break;
}else{
continue;
}
}
if(isLeft){
T += S[left++];
}else{
T += S[right--];
}
}
cout << T;
return 0;
}