字典序最小字符串的操作解析
题目描述
小U拥有一个由0和1组成的字符串,并且可以进行最多k次相邻字符交换操作。我们的目标是通过这些操作,使得最终得到的字符串字典序最小。给定字符串及允许的操作次数,求能达到的字典序最小字符串。
思路分析
为了得到字典序最小的字符串,我们需要将尽可能多的0移动到字符串的前面。具体思路如下:
- 遍历字符串:从左到右遍历字符串,寻找当前字符。
- 移动0到当前位置:当发现当前字符为1时,寻找其后面的0,并计算将这些0移动到当前位置所需的交换次数。
- 判断交换次数:如果所需的交换次数小于或等于k,则进行交换,并更新k值。
- 继续遍历:继续遍历直到达到k的限制或者遍历结束。
图解
假设字符串为 s = "01010",k = 2。
-
初始状态:
0 1 0 1 0 -
第一步:
- 遍历到第一个1(索引1),向后查找0。
- 找到第三个字符0(索引2),需要交换1次(1和0)。
- 交换后得到:
0 0 1 1 0,使用1次操作,k变为1。
-
第二步:
- 接着遍历到第二个1(索引2),向后查找0。
- 找到最后一个字符0(索引4),需要交换2次(1和0,1和0)。
- 交换后得到:
0 0 0 1 1,使用2次操作,k变为0。
最终得到的字符串为 00101。
代码详解
下面是实现该逻辑的 Python 代码:
python
复制
def solution(n: int, k: int, s: str) -> str:
s = list(s) # 将字符串转换为列表,方便修改
for i in range(n):
if k <= 0:
break # 如果没有剩余的交换次数,退出循环
if s[i] == '0':
continue # 如果当前位置已经是0,跳过
# 查找在 i 之后的 '0',并尝试移动到当前位置
for j in range(i + 1, n):
if s[j] == '0':
# 计算移动所需的交换次数
moves = j - i
if moves <= k: # 如果可以在 k 次内完成移动
# 进行交换,把 '0' 移动到当前位置
for x in range(j, i, -1):
s[x] = s[x - 1] # 向右移动
s[i] = '0' # 将 '0' 放在当前位置
k -= moves # 减去使用的交换次数
break # 移动完毕,结束内层循环
return ''.join(s) # 将列表转换回字符串并返回
# 测试代码
if __name__ == '__main__':
print(solution(5, 2, "01010") == '00101') # 输出: True
print(solution(7, 3, "1101001") == '0110101') # 输出: True
print(solution(4, 1, "1001") == '0101') # 输出: True
代码分析
- 字符串转换:首先将字符串转换为列表,以方便对字符进行修改。字符串在Python中是不可变的,因此需要转为列表。
- 外层循环:从左到右遍历字符串,检查每个字符。如果当前字符是0,直接跳过,因为我们希望将0尽量移动到前面。
- 内层循环:对于每个1,向后查找0。如果找到0,计算移动到当前位置所需的交换次数(即索引差)。
- 交换逻辑:如果移动次数在允许的范围内(小于等于k),则进行交换。通过向右移动字符,逐步将0推到当前1的位置。
- 更新状态:在交换后,更新k值和字符状态,继续迭代。若没有足够的交换次数,退出循环。
复杂度分析
- 时间复杂度:O(n^2),最坏情况下,外层循环遍历n次,内层循环也可能遍历n次。
- 空间复杂度:O(n),需要使用额外空间来存储转换后的字符列表。
总结
通过上述算法,我们能够有效地将0移动到字符串的前面,达到字典序最小的目标。关键在于合理判断并执行字符的交换,尽量利用每一次操作。希望这篇笔记能够帮助理解并解决类似的问题。