字节青训营题目: 字典序最小的01字符串
问题描述 传送门
小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'
思路
如果想让结果字典序最小,就需要将字符串左侧的 "1" 尽可能右移。但有可能会遇到多个 "1" 相连的情况 (如测试样例2) , 所以就需要统一处理, 将左侧连续的 "1" 看作整体, 一起右移。
先从左遍历找到第一个1的位置, 再初始化右指针。(用于确定连续1的位置)
用剩余交换次数控制循环,每次从上一次连续1后的位置找连续1后的第一个0:
- 找完整个字符串都没有0,说明此时字典序已经最小了,直接结束循环即可
- 找到后,计算移动连续1的次数,与剩余次数比较
- 剩余交换次数够用,则直接交换此时连续1的头尾,减少交换次数,使头尾指针均右移,准备下次循环
- 剩余交换次数不够,说明这次只够移动一部分的连续1,那就只交换后一部分,交换完成后就是答案
完整代码附上
python是世界上最好的语言.cpp
def solution(n: int, k: int, s: str) -> str:
s = list(s)
# 初始化左指针
i = 0
# 确定第一个1的位置
for i in range(n):
if s[i] == "1":
break
# 初始化右指针
j = i + 1
while k > 0: # 循环判读交换次数
# 确定第一个1之后的第一个0的位置
for j in range(j, n):
if s[j] == "0":
break
elif j == n - 1:
j += 1
break
# 如果右指针到达末尾,则说明已经交换完毕
if j == n:
k = 0
else: # 如果右指针与左指针之间的距离大于交换次数,则交换次数为k
if j - i < k:
# 交换连续1的头尾即可
s[i] = "0"
s[j] = "1"
# 交换次数改变
k -= j - i
# 连续1的左指针右移
i += 1
# 连续1的右指针重置
j += 1
else:
s[j - k] = "0"
s[j] = "1"
k = 0
return "".join(s)
本文来自博客园,作者:ling-yuan,转载请注明原文链接:https://www.cnblogs.com/ling-yuan/p/19053251

浙公网安备 33010602011771号