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

91 阅读4分钟

问题描述

小U拥有一个由0和1组成的字符串,她可以进行最多k次操作,每次操作可以交换相邻的两个字符。目标是通过这些操作,使得最终得到的字符串字典序最小。例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101现在,小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

思路:

  1. 整体思路

    • 核心思路:通过尝试所有可能的相邻字符交换操作(最多 k 次),找到最终字典序最小的字符串。
  2. 具体分析

    • 枚举所有交换情况

      • 由于每次操作只能交换相邻的两个字符,并且最多可以进行 k 次操作,所以这个问题可以看作是一个搜索问题,从初始字符串开始,逐步尝试不同的交换操作。
      • 例如:对于字符串长度为 n,在每一步我们有 n - 1 种可能的相邻交换操作。如果我们把每一次交换看作是一个选择,总共需要做出最多 k 次选择来找到最小字典序的字符串。
    • 递归实现方式

      • 递归方式

        • 从原始字符串开始,每次进行一次相邻字符交换操作,然后递归地调用函数处理交换后的字符串,并且减少剩余的交换次数 k
        • 递归的终止条件是当剩余的交换次数为0时,此时比较当前得到的字符串与之前找到的最小字典序字符串,如果更小则继续更新。

代码实现:

def solution(n: int, k: int, s: str) -> str:
    min_str = s
    def swap(lst, i, j):
        new_lst = lst.copy()
        new_lst[i], new_lst[j] = new_lst[j], new_lst[i]
        return ''.join(new_lst)


    def find_min_str(cur_s, k):
        if k == 0:
            return cur_s
        min_cur_s = cur_s
        for i in range(len(cur_s)-1):
            new_s = swap(list(cur_s), i, i + 1)
            sub_min_s = find_min_str(new_s, k - 1)
            if sub_min_s < min_cur_s:
                min_cur_s = sub_min_s
        return min_cur_s


    min_str = find_min_str(s, k)
    return min_str


if __name__ == '__main__':
    print(solution(5, 2, "01010") == '00101')
    print(solution(7, 3, "1101001") == '0110101')
    print(solution(4, 1, "1001") == '0101')
  1. 核心函数分析

    • find_min_str 函数

      • 这个函数是核心的递归函数,用于寻找经过 k 次交换后的最小字典序字符串。

      • 递归情况:

        • 首先将当前的最小字符串设为当前传入的字符串 cur_s,即 min_cur_s = cur_s
        • 然后遍历当前字符串 cur_s 的每个位置(除了最后一个位置,即 for i in range(len(cur_s)-1))。
        • 在每次遍历中,通过调用 swap 函数交换当前位置 i 和下一个位置 i + 1 的字符,得到新的字符串 new_s
        • 接着,递归调用 find_min_str 函数,传入新字符串 new_s 和剩余交换次数减1(k - 1),得到经过 k - 1 次交换后的最小字典序字符串 sub_min_s
        • 如果 sub_min_s 的字典序小于当前的最小字符串 min_cur_s(在Python中,字符串比较是基于字典序的),则更新 min_cur_s 为 sub_min_s
        • 在遍历完所有可能的交换后,返回找到的最小字典序字符串 min_cur_s
  2. solution 函数整体逻辑

    • 在 solution 函数中,首先将最小字符串 min_str 初始化为输入字符串 s
    • 然后调用 find_min_str 函数,传入输入字符串 s 和可交换次数 k,得到经过 k 次交换后的最小字典序字符串,将结果重新赋值给 min_str
    • 最后返回这个最小字典序字符串 min_str

感悟

  • 递归是这段代码的灵魂所在。当剩余交换次数k为0时,此时直接返回当前的字符串,这是递归的边界条件,它为整个递归过程提供了终止的依据。
  • 在每次递归中,函数尝试通过交换相邻字符来探索所有可能的路径。它先将当前最小字符串设为当前字符串,然后遍历当前字符串的每个可能的交换位置,每次交换后递归地调用自身,减少剩余的交换次数。利用递归的特性巧妙的将一个复杂的多步操作问题逐步分解为一个个简单的子问题