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

36 阅读2分钟

在这篇文章中,我们将深入探讨一种解决特定字符串操作问题的算法,该问题要求通过限定次数的字符交换,实现字符串的字典序最小化。这个问题不仅考验了对字符串操作的理解,还涉及到了贪心算法的应用。

问题概述

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

解题思路

解决这个问题的关键在于贪心地寻找局部最优解,从而达到全局最优解。具体来说,算法的思路是从字符串的左侧开始,尽可能地将'0'移动到字符串的前端。这是因为在字典序中,'0'是小于'1'的,所以字符串的前端越多'0',其字典序越小。

算法的执行步骤如下:

  1. 遍历字符串的每个字符,对于每个位置i,在其后k个字符中寻找字典序最小的字符(即'0'),因为最多可以进行k次操作。
  2. 如果在位置i后的k个字符中找到了'0',那么将这个'0'通过交换移动到位置i上。每进行一次交换,可用的操作数k就减少1。
  3. 重复上述过程,直到遍历完字符串或者没有操作次数为止。

代码解析

public class Main {
    public static String solution(int n, int k, String s) {
        char[] chars = s.toCharArray();
        
        for (int i = 0; i < n && k > 0; i++) {
            // 在[i, min(i + k, n - 1)]范围内寻找最小字符
            int minIndex = i;
            for (int j = i + 1; j <= Math.min(i + k, n - 1); j++) {
                if (chars[j] < chars[minIndex]) {
                    minIndex = j;
                }
            }
            
            // 如果找到了更小的字符,进行交换
            for (int j = minIndex; j > i; j--) {
                // 交换相邻字符
                char temp = chars[j];
                chars[j] = chars[j - 1];
                chars[j - 1] = temp;
                k--; // 每次交换消耗一个操作
                if (k == 0) break; // 如果操作用完,停止
            }
        }
        
        return new String(chars);
    }
}

在这段代码中,chars数组是输入字符串转换而来的字符数组,以便于进行字符的交换操作。外层循环遍历每个字符,内层循环则在当前字符后k个范围内寻找最小的字符(在本题中即为'0')。一旦找到,就通过多次交换,将这个字符移动到当前遍历到的位置。每进行一次交换,k就减少1,直到k用尽为止。

为什么这个方法有效?

这个算法之所以有效,是因为它每次都尽可能地将'0'移动到前面,这样可以保证每一步都是朝着字典序最小的方向前进。同时,通过限制交换次数不超过k,算法确保了操作的可行性。