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

56 阅读3分钟

题目传送门

字典序最小的01字符串 - MarsCode

题意简述

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

解题思路

  • 字符交换策略:为了使字符串的字典序最小,我们需要尽可能地将字符 '0' 移动到字符串的前面。每次操作允许交换相邻的字符,因此我们可以通过逐步交换 '0' 和其左侧的 '1' 来实现这一目标。

  • 贪心算法:采用贪心策略,从左到右遍历字符串,遇到 '0' 时,尽可能地将其向左移动,直到达到边界或用完可用的交换次数 k。这样可以确保每次操作都尽可能地减少字典序。

  • 操作次数限制:在每次交换操作后,减少可用的交换次数 k,并在 k 用完时停止进一步的交换操作。

代码实现

public class Main {
    public static String solution(int n, int k, String s) {
        char[] chars = s.toCharArray(); // 将字符串转换为字符数组

        for (int i = 0; i < n; i++) {
            int j = i;
            // 尝试将当前字符向左移动,直到达到边界或没有足够的交换次数
            while (i > 0 && chars[i - 1] == '1' && chars[i] == '0' && k > 0) {
                // 交换相邻字符
                swap(chars, i, i - 1);
                k--; // 减少可用的交换次数
                i--; // 移动到左边
            }
            i = j; // 恢复i的值
        }

        return new String(chars); // 将字符数组转换回字符串
    }

    // 交换字符数组中两个字符的位置
    private static void swap(char[] chars, int i, int j) {
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;
    }

    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"));
    }
}

时间复杂度分析

该算法的时间复杂度为 𝑂(𝑛^2),其中𝑛是字符串的长度。最坏情况下,每个字符可能需要向左移动多次,导致嵌套循环的存在。然而,由于 k 的限制,实际操作次数通常远小于 𝑛^2。

用到的算法和数据结构

  • 贪心算法:在每一步中,尽可能地将 '0' 向左移动,以减少字典序。

  • 字符数组:用于存储和操作字符串中的字符,便于交换操作。

详细分析

在实现过程中,我们从左到右遍历字符串,遇到 '0' 时,检查其左侧是否有 '1',如果有且 k 大于0,则交换这两个字符,并减少 k。通过这种方式,我们可以在有限的操作次数内,尽可能地将 '0' 移动到字符串的前面,从而使得字符串的字典序最小。这种贪心策略确保了每次操作都尽可能地减少字典序,而不需要考虑全局的最优解,因为每次局部的最优选择(将 '0' 向左移动)最终会导致全局的最优解(字典序最小的字符串)。