3106.满足距离约束且字典序最小的字符串
给你一个字符串 s 和一个整数 k 。
定义函数 distance(s1, s2) ,用于衡量两个长度为 n 的字符串 s1 和 s2 之间的距离,即:
- 字符 ‘a’ 到 ‘z’ 按 循环 顺序排列,对于区间 [0, n - 1] 中的 i ,计算所有「 s1[i] 和 s2[i] 之间 最小距离」的 和 。
例如,distance(“ab”, “cd”) == 4 ,且 distance(“a”, “z”) == 1 。
你可以对字符串 s 执行 任意次 操作。在每次操作中,可以将 s 中的一个字母 改变 为 任意 其他小写英文字母。
返回一个字符串,表示在执行一些操作后你可以得到的 字典序最小 的字符串 t ,且满足 distance(s, t) <= k 。
示例 1:
输入:s = “zbbz”, k = 3
输出:“aaaz”
解释:在这个例子中,可以执行以下操作:
将 s[0] 改为 ‘a’ ,s 变为 “abbz” 。
将 s[1] 改为 ‘a’ ,s 变为 “aabz” 。
将 s[2] 改为 ‘a’ ,s 变为 “aaaz” 。
“zbbz” 和 “aaaz” 之间的距离等于 k = 3 。
可以证明 “aaaz” 是在任意次操作后能够得到的字典序最小的字符串。
因此,答案是 “aaaz” 。
思路:字典序最小的的题目,一般就是贪心或者动态规划,这道题很容易看清是要用贪心。理解题意,我们可以知道,题目就是要让我们从给定的字符串和k,让distance(s, t) <= k ,满足字典序最小。
那么,我们便可以从头开始遍历。字典序最小,我们可以想到如果字符串字符是a,那么无疑是最小的字典序。所以,如果k足够大,我们可以考虑将s[i]直接变成a。这取决于原有字符与a的距离是否≤k。
与a的距离有两种情况,比如d,与a的距离就是d-a;如果是y,距离就是z-y+1。
所以距离满足 int dis = min(s[i]-‘a’,‘z’-s[i]+1)
如果不满足上诉条件,我们就只需要让s[i]尽可能小就可以了。
特殊情况:当k=0时,也就意味着我们不需要进行任何改变,直接return s即可。
AC代码
class Solution {
public:
string getSmallestString(string s, int k) {
if(k==0) return s;
for(int i=0;i<s.size();i++)
{
int dis = min(s[i]-'a','z'-s[i]+1);
if(dis<=k)
{
s[i] = 'a';
k-=dis;
}
else
{
s[i]-=k;
break;
}
}
return s;
}
};