问题要求我们给定一个由 0 和 1 组成的字符串,最多可以进行 k 次相邻字符交换操作,目标是通过这些操作使得最终得到的字符串字典序最小。
关键思路:
- 字典序最小化:字典序最小的字符串意味着将字符串中尽可能多的
0移动到字符串的前面,尽可能多的1移动到后面。所以,我们的目标是通过交换0和1,尽量把0移到前面。 - 操作限制:每次我们只能交换相邻的字符,且每次操作会消耗一次机会(最多进行
k次操作)。
解题步骤:
-
贪心策略:我们从左到右扫描字符串,每遇到一个
1,就尽量将其右边的0向前挪动。我们要寻找一个0,并将它交换到当前1的前面。由于我们只有最多k次操作,因此需要优先交换最小的字符来实现字典序最小。 -
步骤细化:
- 从左到右扫描每一个位置,如果当前位置的字符是
1,我们尝试在当前位置i到i + k之间(即当前1后面最多可以交换的范围)找到最小的字符0,然后将其交换到当前位置。 - 每次交换时要更新剩余的
k,确保不超过最大允许的操作次数。
- 从左到右扫描每一个位置,如果当前位置的字符是
-
优化策略:由于交换是局部的,且我们最多只能交换相邻的字符,因此我们可以通过一次次交换将较小的字符尽量交换到前面。
def solution(n: int, k: int, s: str) -> str:
# 将字符串转换为列表以便进行交换操作
s = list(s)
for i in range(n):
# 在当前位置 i 到 i + k 的范围内找到最小的字符
min_index = i
for j in range(i + 1, min(i + k + 1, n)):
if s[j] < s[min_index]:
min_index = j
# 将找到的最小字符尽可能地向左移动
while min_index > i and k > 0:
# 交换相邻字符
s[min_index], s[min_index - 1] = s[min_index - 1], s[min_index]
min_index -= 1
k -= 1
# 将列表转换回字符串并返回
return ''.join(s)
输入:`n = 7, k = 3, s = "1101001"`
输出:`'0110101'`
-
初始字符串:
1101001,最多可以交换 3 次。 -
在第一次操作时,我们可以交换第二个
1和第三个0,得到1011001。 -
然后交换第三个
1和第四个0,得到0111001。 -
最后交换第四个
1和第五个0,得到0110101,这是字典序最小的字符串。 -
结果为
'0110101'。
复杂度分析:
- 时间复杂度:最坏情况下,我们遍历每个字符并在范围
i到i + k内寻找最小字符,最内层的操作是交换,最坏情况下每个字符都要扫描k次。所以时间复杂度大约是O(n * k),其中n是字符串长度。 - 空间复杂度:由于我们将字符串转换为列表进行操作,额外的空间复杂度为
O(n)。