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

44 阅读3分钟

做题笔记

题目描述

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

解题思路

  1. 目标:通过最多 k 次相邻字符交换操作,使得字符串的字典序最小。

  2. 关键点

    • 字典序最小意味着尽可能多的 0 排在前面。
    • 每次交换操作只能交换相邻的两个字符。

算法步骤

  1. 遍历字符串:从左到右遍历字符串 s,尝试将当前位置的 0 尽可能地往前移动。
  2. 计算交换次数:对于每个 0,计算将其移动到当前位置所需的交换次数。
  3. 判断是否可行:如果当前 0 的交换次数不超过剩余的 k 次,则进行交换;否则,继续遍历。
  4. 更新字符串:每次交换后,更新字符串和剩余的 k 值。

代码实现:

def solution(n: int, k: int, s: str) -> str:
    s_list = list(s)
    count = 0
    while count < k:
        swapped = False
        for i in range(n - 1):  # 避免索引越界
            if s_list[i] == '1' and s_list[i + 1] == '0':
                count += 1
                # 实际的交换操作
                temp = s_list[i]
                s_list[i] = s_list[i + 1]
                s_list[i + 1] = temp
                swapped = True
                break  # 交换后重新从头开始查找
        if not swapped:
            break  # 如果没有发生交换,说明已经无法再优化
    # 将列表转换回字符串并返回
    return ''.join(s_list)

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

关键点解释

  1. 外层循环

    • 使用 while count < k: 循环来控制总的交换次数不超过 k
  2. 内层循环

    • 在每次交换后,使用 break 跳出内层循环,重新从头开始查找交换。
  3. 交换标志

    • 使用 swapped 标志来记录是否发生了交换。如果没有发生交换,说明已经无法再优化,可以提前结束循环。

测试样例

  1. 测试样例 1

    • 输入:n = 5, k = 2, s = "01010"
    • 输出:'00101'
    • 解释:通过两次交换操作,可以将 01010 变为 00101
  2. 测试样例 2

    • 输入:n = 7, k = 3, s = "1101001"
    • 输出:'0110101'
    • 解释:通过三次交换操作,可以将 1101001 变为 0110101
  3. 测试样例 3

    • 输入:n = 4, k = 1, s = "1001"
    • 输出:'0101'
    • 解释:通过一次交换操作,可以将 1001 变为 0101

总结

通过在每次交换后重新从头开始查找交换,可以确保每次交换都能尽可能地优化字符串的字典序。这个方法有效地利用了最多 k 次交换操作,使得最终得到的字符串字典序最小。