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

194 阅读5分钟

一、字典序最小的01字符串问题

1、问题描述

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

例如,小U当前有一个字符串 01010,她最多可以进行 2 次相邻字符交换操作。通过这些操作,她可以将字符串调整为 00101,这是可以通过不超过2次操作得到的字典序最小的字符串。

现在,小U想知道,经过最多k次操作后,能够得到的字典序最小的字符串是什么

2、测试样例

样例1:

输入:n = 5, k = 2, s = "01010"
输出:'00101'

样例2:

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

样例3:

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

二、问题分析

这个问题是一个字符串处理问题,涉及到字符串的排序和交换操作。目标是通过最多k次相邻字符交换操作,使得字符串的字典序最小。这里的字典序是指字符串按照字典顺序排序,即“00101”的字典序小于“01010”。

1、思路解析

  • 理解字典序:字典序最小的字符串意味着在字符串比较时,应该尽可能将较小的字符放在前面。

  • 交换操作:每次操作可以交换相邻的两个字符,目标是将较小的字符移动到更前面的位置。

  • 贪心策略:每次找到当前位置及之后字符中最小的字符,并尝试将其移动到当前位置,这样可以保证每次操作后当前位置及之后的字符串都是字典序最小的。

2、解题步骤

  1. 初始化:将字符串转换为字符数组,方便进行交换操作。
  2.  遍历字符串:从第一个字符开始,遍历整个字符串。
  3.  寻找最小字符:在当前位置及之后的字符中找到最小的字符及其索引。
  4.  计算交换次数:计算将最小字符移动到当前位置所需的交换次数。
  5.  判断是否执行交换:如果交换次数不超过k,则执行交换操作,将最小字符移动到当前位置。
  6.  更新k值:每次执行交换后,更新k的值。
  7.  重复操作:重复步骤3-6,直到遍历完整个字符串。
  8.  返回结果:将字符数组转换回字符串并返回。

三、代码实现

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 minIndex = i;
            for (int j = i + 1; j < n; j++) {
                if (chars[j] < chars[minIndex]) {
                    minIndex = j;
                }
            }
            
            // 计算将最小字符移动到当前位置所需的交换次数
            int swapsNeeded = minIndex - i;
            
            // 如果交换次数不超过 k,则进行交换
            if (swapsNeeded <= k) {
                // 将最小字符移动到当前位置
                while (minIndex > i) {
                    // 交换相邻字符
                    char temp = chars[minIndex];
                    chars[minIndex] = chars[minIndex - 1];
                    chars[minIndex - 1] = temp;
                    minIndex--;
                }
                // 更新 k
                k -= swapsNeeded;
            }
        }
        
        // 将字符数组转换回字符串并返回
        return new String(chars);
    }

    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、时间复杂度分析

  • 外层循环:遍历整个字符串,时间复杂度为O(n)。
  • 内层循环:在每次外层循环中,内层循环同样遍历字符串,时间复杂度为O(n)。
  • 总时间复杂度:由于每次内层循环都会遍历整个字符串,总的时间复杂度为O(n^2)。

2、空间复杂度分析

  • 字符数组:将字符串转换为字符数组,空间复杂度为O(n)。
  • 总空间复杂度:除了输入的字符串外,没有使用额外的空间,因此总的空间复杂度为O(n)。

五、总结

上述算法通过贪心策略,每次找到当前位置及之后字符中最小的字符,并尝试将其移动到当前位置,以此来保证每次操作后当前位置及之后的字符串都是字典序最小的。这种方法简单且有效,但时间复杂度较高,为O(n^2)。空间复杂度为O(n),因为只需要一个额外的字符数组来存储字符串。

代码优化

当前的代码实现虽然已经很好地解决了问题,但是时间复杂度较高。如果需要处理更长的字符串或者更频繁的操作,我们可以考虑以下优化:
1. 减少不必要的交换:在移动最小字符时,可以减少不必要的交换次数,例如,如果最小字符已经在正确的位置,就不需要进行任何交换。
2. 使用更高效的数据结构:例如,使用链表而不是数组来存储字符串,这样可以更高效地进行交换操作。
通过这些优化,可以提高算法的效率,使其能够处理更大规模的数据(具体的代码优化实现就不再给出啦)~~。