做题笔记
题目描述
小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。
解题思路
-
目标:通过最多
k次相邻字符交换操作,使得字符串的字典序最小。 -
关键点:
- 字典序最小意味着尽可能多的
0排在前面。 - 每次交换操作只能交换相邻的两个字符。
- 字典序最小意味着尽可能多的
算法步骤
- 遍历字符串:从左到右遍历字符串
s,尝试将当前位置的0尽可能地往前移动。 - 计算交换次数:对于每个
0,计算将其移动到当前位置所需的交换次数。 - 判断是否可行:如果当前
0的交换次数不超过剩余的k次,则进行交换;否则,继续遍历。 - 更新字符串:每次交换后,更新字符串和剩余的
k值。
代码实现:
def solution(n: int, k: int, s: str) -> str:
s_list = list(s)
count = 0
while count < k:
swapped = False
for i in range(n - 1): # 避免索引越界
if s_list[i] == '1' and s_list[i + 1] == '0':
count += 1
# 实际的交换操作
temp = s_list[i]
s_list[i] = s_list[i + 1]
s_list[i + 1] = temp
swapped = True
break # 交换后重新从头开始查找
if not swapped:
break # 如果没有发生交换,说明已经无法再优化
# 将列表转换回字符串并返回
return ''.join(s_list)
if __name__ == '__main__':
print(solution(5, 2, "01010") == '00101')
print(solution(7, 3, "1101001") == '0110101')
print(solution(4, 1, "1001") == '0101')
关键点解释
-
外层循环:
- 使用
while count < k:循环来控制总的交换次数不超过k。
- 使用
-
内层循环:
- 在每次交换后,使用
break跳出内层循环,重新从头开始查找交换。
- 在每次交换后,使用
-
交换标志:
- 使用
swapped标志来记录是否发生了交换。如果没有发生交换,说明已经无法再优化,可以提前结束循环。
- 使用
测试样例
-
测试样例 1:
- 输入:
n = 5, k = 2, s = "01010" - 输出:
'00101' - 解释:通过两次交换操作,可以将
01010变为00101。
- 输入:
-
测试样例 2:
- 输入:
n = 7, k = 3, s = "1101001" - 输出:
'0110101' - 解释:通过三次交换操作,可以将
1101001变为0110101。
- 输入:
-
测试样例 3:
- 输入:
n = 4, k = 1, s = "1001" - 输出:
'0101' - 解释:通过一次交换操作,可以将
1001变为0101。
- 输入:
总结
通过在每次交换后重新从头开始查找交换,可以确保每次交换都能尽可能地优化字符串的字典序。这个方法有效地利用了最多 k 次交换操作,使得最终得到的字符串字典序最小。