字典序最小的01字符串 | 豆包MarsCode AI 刷题

51 阅读3分钟

字典序最小的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 尽可能靠左,符合贪心思想。当 k0或者扫描到达字符串末尾时得到的字符串即为字典序最小的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. 时间复杂度

代码的主要部分是一个外层遍历和内层嵌套循环:

  1. 外层遍历

    • 外层循环遍历字符串,从左到右,最多运行 O(n)O(n) 次,其中 nn 是字符串的长度。
  2. 内层循环

    • 内层循环负责将 0 和其左侧的 1 交换,每次交换会减少 kk 的值。
    • 每次遇到一个 10,内层循环最多运行与当前交换的步数相关的次数。如果交换总次数受到 kk 的限制,那么所有交换次数加起来最多为 O(k)O(k)
  3. 总体复杂度

    • 外层循环会扫描整个字符串,但每次执行内层循环时,操作总数会严格减少 kk,因此内层循环的累计次数总和不会超过 kk
    • 因此,总体时间复杂度为 O(n+k)O(n + k)