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

99 阅读2分钟

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)O(n)
    • 更新字符串,同时减少相应的操作次数k

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

代码实现

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)

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