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

48 阅读4分钟

问题背景

小U拥有一个仅由01组成的字符串,她最多可以进行k次操作,每次操作允许交换相邻的两个字符。目标是通过这些有限的操作,将字符串调整为字典序最小。

什么是字典序最小? 字典序是指将字符串按照字母表顺序排列的规则。例如:

  • 字符串01010的字典序小于10100,因为它在比较时前面部分就小于后者。

假设小U当前的字符串为01010,最多可以进行2次操作:

  1. 交换第2位和第3位(形成00110)。
  2. 交换第3位和第4位(形成00101)。 最终,得到字典序最小的字符串00101

解决思路

为了有效解决这个问题,我们选择一种 贪心算法,这是一种逐步选择当前最佳操作的算法,能够快速找到局部最优解,并在某些情况下接近全局最优解。贪心算法适用于此问题,因为:

  • 每次交换的目的是尽可能让左侧字符更小。
  • 通过局部调整,逐步接近全局最优解。

具体来说,本问题的核心思路如下:

  1. 逐步定位最优字符:从左到右遍历字符串,依次确定当前最优字符(字典序最小)。
  2. 限制交换范围:在保证操作次数不超过k的前提下,寻找可以移动到当前位置的最小字符。
  3. 逐步交换调整:将目标字符移动到当前位置,同时更新剩余可用操作次数k
  4. 终止条件:若操作次数用尽或所有字符已调整完成,则停止操作。

算法设计

基于上述思路,我们设计如下算法流程:

  1. 初始化输入参数:

    • 字符串长度n,最大操作次数k,以及字符串s
  2. 遍历字符串:

    • 当前考察位置为i
    • i后续范围内(满足j - i <= k),寻找最小字符的位置minIndex
  3. minIndex位置的字符移动到i

    • 通过逐步交换,将该字符左移到i
    • 减少剩余操作次数:k -= (minIndex - i)
  4. 重复步骤2和3,直到k耗尽或遍历完成。

  5. 返回调整后的字符串。


算法实现

以下是使用Java实现上述算法的代码:

public class Main {
    public static String solution(int n, int k, String s) {
        char[] arr = s.toCharArray(); // 将字符串转化为字符数组便于操作
        int remainingSwaps = k;       // 剩余的操作次数

        for (int i = 0; i < n && remainingSwaps > 0; i++) {
            // 找到可以在当前范围内移动的最小字符
            int minIndex = i;
            for (int j = i + 1; j < n && j - i <= remainingSwaps; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }

            // 将最小字符移动到当前位置
            for (int j = minIndex; j > i; j--) {
                char temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
            }

            // 更新剩余操作次数
            remainingSwaps -= (minIndex - i);
        }

        return new String(arr); // 返回最终调整后的字符串
    }

    public static void main(String[] args) {
        System.out.println(solution(5, 2, "01010").equals("00101"));
        System.out.println(solution(7, 3, "1101001").equals("0110101"));
        System.out.println(solution(4, 1, "1001").equals("0101"));
    }
}

复杂度分析

  1. 时间复杂度

    • 外层循环最多执行n次(字符串长度)。
    • 内层循环每次最多遍历k个字符。
    • 因此时间复杂度为O(n * k)
  2. 空间复杂度

    • 使用了字符数组arr,占用O(n)空间。
    • 无额外的数据结构开销,因此总空间复杂度为O(n)

优化与扩展

  1. 时间复杂度优化

    • 如果k远小于n,可以使用堆(Heap)等数据结构快速找到最小字符的位置。
    • 使用双指针方法减少内层循环的复杂性。
  2. 扩展到其他字符集

    • 本问题目前限定字符为01,可以轻松扩展到全字符集,例如字母和数字。
  3. 动态规划优化

    • 如果k较大且字符串长度较长,可以尝试动态规划记录每个字符的最优位置。

总结

本文通过深入分析“小U调整字符串字典序最小化”问题,详细描述了贪心算法的实现过程。该算法通过逐步优化字符位置,在有限操作次数内逼近最优解。其高效性和可扩展性使得它成为解决此类问题的理想选择。希望通过本文的讲解,读者能够掌握贪心算法在字符串处理中的应用,并进一步思考算法优化与扩展的可能性。