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

1 阅读3分钟

问题描述

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

例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过2次操作得到的字典序最小的字符串。

现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么。


测试样例

样例1:

输入:n = 5, k = 2, s = "01010"
输出:'00101'

样例2:

输入:n = 7, k = 3, s = "1101001"
输出:'0110101'

样例3:

输入:n = 4, k = 1, s = "1001"
输出:'0101'

思路分析

这道题其实用贪心算法就能很好地解决。贪心算法的核心思想就是每一步都选择当前情况下最优的操作,最终得到一个全局最优的结果。在这个问题中,我们的目标是尽量把'0'往前移动。因此,我们可以从左到右遍历字符串,每次遇到'0',就尽可能将它往左移动,同时确保总的操作次数不超过k次。

我们可以用一个列表result来存储当前的字符序列。当遍历字符串时,如果遇到字符'0',我们希望它尽可能往前移动。移动的次数不能超过当前已有'1'的数量,并且总操作次数也不能超过k。因此,每次遇到'0'时,计算它最多能移动的距离,然后把它插入到合适的位置。对于字符'1',直接添加到列表的末尾就可以。

Python代码

def solution(n, k, s):
    result = []
    onenum = 0
    for i in range(n):
        if s[i] == "0":
            move = min(k, onenum)
            pos = len(result) - move
            result.insert(pos, "0")
            k -= move
        else:
            result.append("1")
            onenum += 1
    return "".join(result)

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

代码详解

  1. 变量初始化

    • result:用于存储当前处理后的字符序列,初始为空。
    • onenum:用于记录当前遇到的'1'的数量。
  2. 遍历字符串

    • 对于每一个字符,如果是'0',就尝试将它移动到尽可能靠前的位置。移动的次数由min(k, onenum)决定,表示'0'最多可以向左移动onenum次,但不能超过剩余的操作次数k
    • 计算出'0'应该插入的位置,然后将它插入到result中对应的位置。
    • 如果是'1',直接将它添加到result的末尾,并增加onenum的计数。
  3. 结果返回

    • 最后,将列表result转换为字符串并返回。

复杂度分析

这个算法的时间复杂度是O(n2)O(n^2),因为在最坏的情况下,每次插入操作的时间复杂度是O(n)O(n)。对于较长的字符串,可能会导致效率问题。不过,由于题目限制是相邻交换,插入操作的次数其实受到k的限制,所以在实际运行中效率还可以接受。

吐槽

我不知道这道题是怎么被定为“困难题”的,大概是为了让我们能够达到入营需求,专门放置的水题罢。不过作为简单题用来练手还是不错的。