19 字典序最小的 01 字符串 简单 O(n)做法

19 字典序最小的 01 字符串 简单 O(n)做法

题目描述

小 U 拥有一个由01组成的字符串,她可以进行最多k次操作。每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。

解题思路

为了获得字典序最小的字符串,我们的目标是尽可能将'0'移向字符串的左侧而把'1'移到字符串的右侧,并且根据字典序的规则,我们应该尽量把'1'和最右边的'0'交换

具体步骤如下:

  1. 遍历字符串:从左到右遍历字符串中的每一个字符。
  2. 遇到'0'时尝试和左边的最远的'1'交换
    • 对于当前位置的'0',尝试将其向左边移动尽可能多的位置,但移动的步数不能超过剩余的操作次数ops
    • 用指针j记录最左边的'1'的位置,并且j具有单调性,因为假设当前的i - j > ops,这意味着本次不能交换,那么当i继续向右移动时,i - j的值只会越来越大,所以j也必须向右继续移动才有可能进行交换。这也意味这j只会从0~n遍历一次,复杂度为$O(n)$
    • 更新字符串,同时减少相应的操作次数k

这种方法确保了在每一步操作中,都将当前的'0'尽可能地向左移动,从而整体上达到了字典序最小的目标。

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def solution(n: int, ops: int, s: str) -> str:
s = list(s)
j = 0
for i in range(n):
if s[i] == '0':
for k in range(j, i):
if s[k] == '1' and (i - k) <= ops:
s[k] = '0'
s[i] = '1'
ops -= (i - k)
j = k + 1 # 更新j的位置
break
return "".join(s)

if __name__ == '__main__':
print(solution(5, 2, "01010") == '00101')
print(solution(7, 3, "1101001") == '0110101')
print(solution(4, 1, "1001") == '0101')

复杂度分析
时间复杂度:$O(n)$

空间复杂度:$O(n)$
用于存储可变的字符串列表。


19 字典序最小的 01 字符串 简单 O(n)做法
https://kongshuilinhua.github.io/2024/12/22/19-字典序最小的-01-字符串-简单-O-n-做法/
作者
FireFLy
发布于
2024年12月22日
许可协议