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

112 阅读3分钟

题目解析

问题描述

小U拥有一个由 01 组成的字符串,她可以最多进行 kk 次相邻字符交换操作。目标是通过这些操作,使字符串的字典序尽可能小。

字典序的定义是:在从左到右逐字符比较两个字符串时,越早遇到较小字符的字符串字典序越小。


解题思路

核心思想

目标是将 0 尽可能移动到字符串的左侧,但每个 0 的移动需要尽量利用有限的 kk 次操作。

贪心策略

  1. 逐个处理每个 0:从左到右遍历字符串,找到每个 0 的位置。
  2. 计算可移动距离:对于第 i 个 0
    • 统计它与前面的 1 之间的距离。
    • 如果距离超过剩余的 k,则只能移动 k 步。
  3. 实际移动操作
    • 0 向左移动所能达到的位置,更新字符串和剩余的 kk 值。
  4. 提前结束:如果 k 耗尽,直接终止操作。

代码实现

def solution(n: int, k: int, s: str) -> str:
    # 将字符串转换为列表,方便操作
    s = list(s)
    
    # 从左到右遍历字符串,找到每个 '0' 并尽量向左移动
    for i in range(n):
        if s[i] == '0':
            # 初始化可以移动的步数
            move_steps = 0
            # 计算这个 '0' 前有多少个连续的 '1' 可以交换
            for j in range(i - 1, -1, -1):
                if s[j] == '1':
                    move_steps += 1
                else:
                    break
            
            # 实际可以移动的步数是 move_steps 和 k 的最小值
            steps = min(move_steps, k)
            
            # 如果可以移动,则移动
            if steps > 0:
                # 移动 '0' 并更新字符串
                s[i], s[i - steps] = s[i - steps], s[i]
                # 减少操作次数
                k -= steps
            
            # 如果操作次数已经用尽,直接结束
            if k == 0:
                break
    
    # 返回结果
    return ''.join(s)

# 测试样例
if __name__ == '__main__':
    print(solution(5, 2, "01010") == '00101')  # 输出: '00101'
    print(solution(7, 3, "1101001") == '0110101')  # 输出: '0110101'
    print(solution(4, 1, "1001") == '0101')  # 输出: '0101'

样例解析

样例1

输入:n=5,k=2,s="01010" 操作过程

  1. 初始字符串:01010
    • 第一个 0 在位置 1,与前面 1 的距离为 1,移动 1 步:00110
    • 第二个 0 在位置 3,与前面 1 的距离为 1,移动 1 步:00101
  2. 剩余 k=0,操作结束。

输出:00101


样例2

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

操作过程

  1. 初始字符串:1101001
    • 第一个 0 在位置 2,与前面 1 的距离为 2,移动 2 步:1011001
    • 第二个 0 在位置 4,与前面 1 的距离为 1,移动 1 步:0110101
  2. 剩余 k=0,操作结束。

输出:0110101


样例3

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

操作过程

  1. 初始字符串:1001
    • 第一个 0 在位置 1,与前面 1 的距离为 1,移动 1 步:0101
  2. 剩余 k=0,操作结束。

输出:0101


复杂度分析

  1. 时间复杂度

    • 外层循环遍历每个字符,复杂度为 O(n)。
    • 内层计算 0 前面的 1,最坏情况下需要 O(n)。
    • 总复杂度为 O(n^2)。
  2. 空间复杂度

    • 转换为列表存储字符串,复杂度为 O(n)。

优化思路

在内层遍历时,可以通过维护一个前缀数组记录每个位置前面的 1 数量,减少重复计算,优化为 O(n)。