难度:中等
给你一个字符串 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" 。
示例 2:
输入:s = "xaxcd", k = 4
输出:"aawcd"
解释:在这个例子中,可以执行以下操作:
将 s[0] 改为 'a' ,s 变为 "aaxcd" 。
将 s[2] 改为 'w' ,s 变为 "aawcd" 。
"xaxcd" 和 "aawcd" 之间的距离等于 k = 4 。
可以证明 "aawcd" 是在任意次操作后能够得到的字典序最小的字符串。
因此,答案是 "aawcd" 。
示例 3:
输入:s = "lol", k = 0
输出:"lol"
解释:在这个例子中,k = 0,更改任何字符都会使得距离大于 0 。
因此,答案是 "lol" 。
提示
1 <= s.length <= 100
0 <= k <= 2000
s 只包含小写英文字母。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
这道中等题还是比较简单的,一般要求最大最小什么的,思路尽量往贪心上靠,如果不行就只能上dp了,或者记忆化搜索之类的,都是用来求最值的。
这道题求的是字典序最小,并且限制距离,所以要利用最小的距离去变成字典序最小,所以一定是从前往后开始遍历的,并且除非原本就是'a',否则不能跳过,因为往'a'靠肯定是最小的,所以直接贪心就完了。
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
var getSmallestString = function(s, k) {
// 从第一个字母开始变,尽量贴近a(保证字典序最小)
let t = s.split("")
// let d = k
const a = 'a'.charCodeAt(), z = 'z'.charCodeAt()
for(let i = 0; i < t.length; i ++) {
c = t[i]
const d2a = getDis(c, 'a')
// 如果到a的距离小于等于 到前面极限位置的字母的距离,则优先变a,如果变大直接换下一位
if (d2a <= k) { // 直接变a的
t[i] = 'a'
k -= d2a
} else { // 到a的距离大于k,则往前k位变
t[i] = String.fromCharCode(c.charCodeAt() - k)
k = 0
}
if (k == 0) break
}
return t.join("")
};
function getDis(c1, c2) {
const d = Math.abs(c1.charCodeAt() - c2.charCodeAt())
return Math.min(d, 26-d)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31