问题描述
小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。例如,小U当前有一个字符串
01010,她最多可以进行2次相邻字符交换操作。通过这些操作,她可以将字符串调整为
00101,这是可以通过不超过2次操作得到的字典序最小的字符串。 现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。
测试样例
输入:n = 5, k = 2, s = "01010" 输出:'00101'
解题思路
- 理解问题:
- 我们有一个由
0和1组成的字符串。 - 我们可以进行最多
k次相邻字符的交换操作。 - 目标是使得字符串的字典序最小。
- 数据结构选择:
- 使用字符串来表示当前的字符串状态。
- 使用一个计数器来跟踪剩余的交换次数。
- 算法步骤:
- 从字符串的第一个字符开始,尝试将当前字符与后面的字符进行交换,以使得字符串的字典序最小。
- 每次交换后,更新剩余的交换次数。
- 如果剩余的交换次数不足以进行进一步的交换,则停止操作。
代码框架
def solution(n: int, k: int, s: str) -> str:
s = list(s) # 将字符串转换为列表以便进行交换操作
for i in range(n):
if k == 0:
break
# 找到从i开始的最小字符及其位置
min_char = s[i]
min_index = i
for j in range(i + 1, min(i + k + 1, n)):
if s[j] < min_char:
min_char = s[j]
min_index = j
# 将最小字符交换到当前位置
while min_index > i:
s[min_index], s[min_index - 1] = s[min_index - 1], s[min_index]
min_index -= 1
k -= 1
return ''.join(s)
if __name__ == '__main__':
print(solution(5, 2, "01010") == '00101')
print(solution(7, 3, "1101001") == '0110101')
print(solution(4, 1, "1001") == '0101')
详细解释
循环查找最小字符
for j in range(i + 1, min(i + k + 1, n)):
if s[j] < min_char:
min_char = s[j]
min_index = j
- 初始条件:
i是当前需要放置最小字符的位置。k是剩余的交换次数。n是字符串的长度。min_char是当前位置i的字符。min_index是当前位置i的索引。
- 循环范围:
for j in range(i + 1, min(i + k + 1, n))::i + 1表示从当前位置i的下一个位置开始。min(i + k + 1, n)表示循环的结束位置。这里使用了min函数来确保不会超出字符串的长度n,同时限制在当前位置i之后的k + 1个字符范围内。
- 查找最小字符:
if s[j] < min_char::- 如果当前字符
s[j]小于min_char,则更新min_char和min_index。 min_char = s[j]:- 更新
min_char为当前字符s[j]。 min_index = j:- 更新
min_index为当前字符s[j]的索引j。
交换字符并更新操作次数
while min_index > i:
s[min_index], s[min_index - 1] = s[min_index - 1], s[min_index]
min_index -= 1
k -= 1
假设当前字符串为 s = "01010",i = 1,min_index = 3,k = 2。
- 初始状态:
s = "01010",min_index = 3,i = 1,k = 2。 - 第一次交换:
s[3]和s[2]交换,字符串变为"01001",min_index = 2,k = 1。 - 第二次交换:
s[2]和s[1]交换,字符串变为"00101",min_index = 1,k = 0。 - 此时,
min_index已经等于i,循环结束,最小字符0已经移动到了当前位置i。
结语
本篇文章详细的介绍了一种解答方法,首先遍历字符串找到最小的字符集其位置,然后将最小字符串交换位置,最后返回结果。
需要注意的是:k(剩余交换次数)的检查以及返回结果时s需要将列表转换成字符串。
希望此篇文章对您有所帮助