问题描述
小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。
例如,小U当前有一个字符串 01010
,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101
,这是可以通过不超过2次操作得到的字典序最小的字符串。
现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。
测试样例
样例1:
输入:
n = 5, k = 2, s = "01010"
输出:'00101'
样例2:
输入:
n = 7, k = 3, s = "1101001"
输出:'0110101'
样例3:
输入:
n = 4, k = 1, s = "1001"
输出:'0101'
解题思路
这个问题是一个典型的字符串操作问题,目标是通过交换相邻字符使得字符串的字典序最小化。这里的操作方法是我们需要将字符串中的字符按照从小到大的顺序重新排列,但只能通过交换相邻的字符并且交换的次数不能超过给定的k次。 对于这个问题,我们可以采用贪心策略,每次交换都尽可能的将字符串前面的1与后面的0交换,并且结合递归,在每次交换完最前面的1和0之后,需要重新计算最前面的1和0所在的位置。 步骤详解:
-
首先将字符串s转换为字符数组,使用一个循环从左到右遍历字符数组,寻找第一个1和它后面的第一个0,如果1在0的左边,并且剩余的交换次数k大于0,则交换这两个字符,并将操作次数k减1。
-
第一个1和0字符交换之后就传入当前修改之后的字符串进行下一次递归,这样可以保证每次交换的就是最前面的1和0,是的字符串的字典序变得最小。
-
如果k减到0,则停止交换,将数组转换为字符串并返回结果。
-
如果遍历完整个数组都没有交换完成,或者k已经减到0,则将数组转换为字符串并返回结果。
代码实现
function solution(n, k, s) {
function changeChar(newArray) {
for (let i = 0; i < n - 1; i++) {
if (newArray[i] === "1" && newArray[i + 1] === "0") {
[newArray[i], newArray[i + 1]] = [newArray[i + 1], newArray[i]]
k--
if (k <= 0) return newArray.join('')
//将当前字符串传入下一次递归,保证字符串的最前面的1和0能够进行交换
return changeChar(newArray)
}
}
return newArray.join('')
}
return changeChar(s.split(''));
}
function main() {
console.log(solution(5, 2, "01010") === "00101");
console.log(solution(7, 3, "1101001") === "0110101");
console.log(solution(4, 1, "1001") === "0101");
}
main();