题目链接
脑子比较笨,分三种情况考虑:
- 以a开头。
- xxa,a在中间。
对于情况2还有两种可能:- 全是a,最后一个元素需要替换成z,因为必须执行一次操作。
- aaaxxa,中间有一段非a,将这段改变即可。
垃圾实现代码:
cpp
class Solution {
public:
string smallestString(string s) {
int fidx = -1, sidx = -1;
string ans = "";
for (int i = 0; i < s.size(); i ++ ) {
if (s[i] == 'a') {
fidx = i;
break;
}
}
if (fidx == 0) {// a 开头的
int j = 0;
while(s[j] == 'a') {
j ++;
}
// j 第一个不是a的元素
if (j == s.size()) { // 全是a
for (int i = 0; i < s.size(); i ++ ) {
ans += s[i];
}
ans[s.size() - 1] = 'z';
return ans;
} else { // aaaa xxxxx a
for (; j < s.size(); j ++ ) {
if (s[j] == 'a') {
sidx = j;
break;
}
}
for (int i = 0; i < s.size(); i ++ ) {
if (i < j && s[i] !='a') {
ans += (s[i] - 1);
} else {
ans += s[i];
}
}
return ans;
}
} else if (fidx != -1 ){ // bbb a
for (int i = 0; i < s.size(); i ++ ) {
if (i < fidx) {
ans += (s[i] - 1);
} else {
ans += s[i];
}
}
return ans;
} else {
for (int i = 0; i < s.size(); i ++ ) {
ans += (s[i] - 1);
}
return ans;
}
}
};
灵神的代码(我的看起来好傻):
从左到右找到第一个不等于 a 的字符 s[i],然后从 i 开始,把每个字符都减一,直到遍历结束或者遇到了 a。例如 abca 操作中间的子串 bc,得到答案 aaba。
细节:如果 s 全为 a,由于题目要求必须操作一次,可以把最后一个 a 改成 z。
cpp
class Solution {
public:
string smallestString(string s) {
int n = s.length();
for (int i = 0; i < n; i++) {
if (s[i] > 'a') {
// 继续向后遍历
for (; i < n && s[i] > 'a'; i++) {
s[i]--;
}
return s;
}
}
// 所有字母均为 a
s.back() = 'z';
return s;
}
};