字典序最小的01字符串 | 豆包MarsCode AI 刷题
问题描述
小U拥有一个由 0 和 1 组成的字符串,她可以进行最多 k 次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。
例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过 2 次操作得到的字典序最小的字符串。
现在,小U想知道,经过最多 k 次操作后,能够得到的字典序最小的字符串是什么。
思路
该问题要求我们在有限次 k 操作内,通过交换相邻字符,将字符串调整为字典序最小的形式。为了得到字典序最小的字符串,显然应尽可能多地将 0 移动到前面。
对于一次交换有四种情况:相邻字符为 11 、 相邻字符为 00 、 相邻字符为 01 、 相邻字符为 10 , 显然,对于前三种情况不应该进行交换,因为交换 11 或者 00 不会改变原字符串的字典序,交换 01 会增大字典序。我们只需要查找 10 出现的位置。
每次交换 10 都可以将 0 向左移动,减少字典序的大小。所以我们应该从左到右扫描字符串,找到第一个 10 的位置。尽可能多次地将该 10 中的 0 向左移动。这样可以确保在当前位置将 0 尽可能靠左,符合贪心思想。当 k 为 0或者扫描到达字符串末尾时得到的字符串即为字典序最小的01字符串。
代码实现
def solution(n: int, k: int, s: str) -> str:
if len(s) < 2:
return s
#转成列表,python不能直接对字符串进行操作
sl = list(s)
s_len = len(sl)
i = 1
while i < s_len and k > 0:
while i >= 1 and sl[i] == '0' and sl[i-1] == '1' and k > 0:
sl[i-1], sl[i] = sl[i], sl[i-1]
i -= 1
k -= 1
i += 1
return ''.join(sl)
if __name__ == '__main__':
#test cases...
或者用replace:
def solution(n: int, k: int, s: str) -> str:
while k > 0:
s = s.replace('10','01',1)
k -= 1
return s
更短的代码:
def solution(n: int, k: int, s: str) -> str:
return s if k == 0 else solution(n, k - 1, s.replace('10', '01', 1))
if __name__ == '__main__':
#test cases...
复杂度分析
1. 时间复杂度
代码的主要部分是一个外层遍历和内层嵌套循环:
-
外层遍历:
- 外层循环遍历字符串,从左到右,最多运行 次,其中 是字符串的长度。
-
内层循环:
- 内层循环负责将
0和其左侧的1交换,每次交换会减少 的值。 - 每次遇到一个
10,内层循环最多运行与当前交换的步数相关的次数。如果交换总次数受到 的限制,那么所有交换次数加起来最多为 。
- 内层循环负责将
-
总体复杂度:
- 外层循环会扫描整个字符串,但每次执行内层循环时,操作总数会严格减少 ,因此内层循环的累计次数总和不会超过 。
- 因此,总体时间复杂度为 。