2734.执行子串操作后的字典序最小字符串

【LetMeFly】2734.执行子串操作后的字典序最小字符串:贪心

力扣题目链接:https://leetcode.cn/problems/lexicographically-smallest-string-after-substring-operation/

给你一个仅由小写英文字母组成的字符串 s 。在一步操作中,你可以完成以下行为:

  • 选择 s 的任一非空子字符串,可能是整个字符串,接着将字符串中的每一个字符替换为英文字母表中的前一个字符。例如,'b' 用 'a' 替换,'a' 用 'z' 替换。

返回执行上述操作 恰好一次 后可以获得的 字典序最小 的字符串。

子字符串 是字符串中的一个连续字符序列。

现有长度相同的两个字符串 x 和 字符串 y ,在满足 x[i] != y[i] 的第一个位置 i 上,如果  x[i] 在字母表中先于 y[i] 出现,则认为字符串 x 比字符串 y 字典序更小

 

示例 1:

输入:s = "cbabc"
输出:"baabc"
解释:我们选择从下标 0 开始、到下标 1 结束的子字符串执行操作。 
可以证明最终得到的字符串是字典序最小的。

示例 2:

输入:s = "acbbc"
输出:"abaab"
解释:我们选择从下标 1 开始、到下标 4 结束的子字符串执行操作。
可以证明最终得到的字符串是字典序最小的。

示例 3:

输入:s = "leetcode"
输出:"kddsbncd"
解释:我们选择整个字符串执行操作。
可以证明最终得到的字符串是字典序最小的。

 

提示:

  • 1 <= s.length <= 3 * 105
  • s 仅由小写英文字母组成

解题方法:贪心

定理一:前面字符的修改比后面字符修改的影响大。

例如对于字符串czzzzzz,假设给你两种选择让你选一个:

  1. 把后面的z全改成acaaaaaa
  2. 将一个c改成bbzzzzzz

那当然选择方案1.

定理二:对a操作是无意义的。

对于其他任何字符串而言,一次“操作”都会让字符的字典序变地更小。

而对a进行一次操作后只会让a变成z(变地更大)。

并且由定理一可知,为了让a后面的字符变地更小而连上a是无意义的。

例如zzzazzzzz最优解是变成yyyazzzzz,而不能为了将后面的zzzzz变成yyyyy而将a变成b

因此,我们可以从第一个非a字符开始,到a字符或字符串末尾或为止,对其组成的子字符串进行一次操作。

特别的,题目要求对子字符串非空。因此若字符串为“全a”,那么就将最后一个a变成z

  • 时间复杂度$O(len(s))$
  • 空间复杂度$O(1)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
string smallestString(string s) {
bool changing = false;
int loc = 0;
while (loc < s.size() && s[loc] == 'a') {
loc++;
}
if (loc == s.size()) { // 特判:全a的情况
s.back() = 'z';
return s;
}
for (; loc < s.size() && s[loc] != 'a'; loc++) {
s[loc]--;
}
return s;
}
};

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

Tisfy:https://letmefly.blog.csdn.net/article/details/140027022


2734.执行子串操作后的字典序最小字符串
https://blog.letmefly.xyz/2024/06/27/LeetCode 2734.执行子串操作后的字典序最小字符串/
作者
Tisfy
发布于
2024年6月27日
许可协议