最小非递减子字符串成本|豆包MarsCodeAI刷题

83 阅读3分钟

问题理解

我们需要找到字符串 S 的“成本”,定义为:字符串中按非递减顺序排列的最长子字符串的长度。然后,我们可以进行最多一次交换操作,选择一个位置 i (0 <= i < N-1),并交换 S[i] 和 S[i+1],以最小化这个成本。

数据结构选择

我们可以使用数组来存储字符串 S 的字符,并使用变量来记录当前的最长非递减子字符串的长度。

算法步骤

  1. 初始化:遍历字符串 S,计算不进行任何交换时的最长非递减子字符串的长度。
  2. 尝试交换:对于每个可能的交换位置 i,尝试交换 S[i] 和 S[i+1],并计算交换后的最长非递减子字符串的长度。
  3. 更新最小成本:在所有可能的交换中,选择使得最长非递减子字符串长度最小的那个。

思路提示

  1. 计算初始最长非递减子字符串的长度

    • 遍历字符串 S,记录当前的最长非递减子字符串的长度。
    • 如果当前字符 S[i] 大于等于前一个字符 S[i-1],则当前子字符串长度 currentLength 加一。
    • 否则,重置 currentLength 为 1。
    • 更新 maxLength 为 currentLength 和 maxLength 中的最大值。
  2. 尝试交换

    • 对于每个可能的交换位置 i,生成新的字符串并计算交换后的最长非递减子字符串的长度。
    • 交换 S[i] 和 S[i+1] 后,再次遍历字符串,计算新的最长非递减子字符串的长度。
    • 更新 maxLength 为当前 maxLength 和交换后的最长非递减子字符串长度中的最小值。
  3. 更新最小成本

    • 在所有可能的交换中,选择使得最长非递减子字符串长度最小的那个。
public class Main {
    public static int solution(int N, String S) {
        // 初始化最长非递减子字符串的长度
        int maxLength = 1;
        int currentLength = 1;

        // 计算不进行任何交换时的最长非递减子字符串的长度
        for (int i = 1; i < N; i++) {
            if (S.charAt(i) >= S.charAt(i - 1)) {
                currentLength++;
            } else {
                currentLength = 1;
            }
            maxLength = Math.max(maxLength, currentLength);
        }

        // 尝试交换每个位置 i 和 i+1
        for (int i = 0; i < N - 1; i++) {
            // 交换 S[i] 和 S[i+1]
            String swappedString = swap(S, i, i + 1);

            // 计算交换后的最长非递减子字符串的长度
            int swappedMaxLength = 1;
            int swappedCurrentLength = 1;
            for (int j = 1; j < N; j++) {
                if (swappedString.charAt(j) >= swappedString.charAt(j - 1)) {
                    swappedCurrentLength++;
                } else {
                    swappedCurrentLength = 1;
                }
                swappedMaxLength = Math.max(swappedMaxLength, swappedCurrentLength);
            }

            // 更新最小成本
            maxLength = Math.min(maxLength, swappedMaxLength);
        }

        return maxLength;
    }

    // 辅助函数:交换字符串中两个位置的字符
    private static String swap(String s, int i, int j) {
        char[] chars = s.toCharArray();
        char temp = chars[i];
        chars[i] = chars[j];
        chars[j] = temp;
        return new String(chars);
    }

    public static void main(String[] args) {
        System.out.println(solution(4, "abba") == 2);
        System.out.println(solution(5, "baabb") == 2);
        System.out.println(solution(3, "bab") == 2);
    }
}
### 关键步骤

1.  **计算初始最长非递减子字符串的长度**:遍历字符串 `S`,记录当前的最长非递减子字符串的长度。
1.  **尝试交换**:对于每个可能的交换位置 `i`,生成新的字符串并计算交换后的最长非递减子字符串的长度。
1.  **更新最小成本**:在所有可能的交换中,选择使得最长非递减子字符串长度最小的那个。

### 测试样例

-   输入:`N = 4, S = "abba"`,输出:`2`
-   输入:`N = 5, S = "baabb"`,输出:`2`
-   输入:`N = 3, S = "bab"`,输出:`2`

通过这些步骤,希望对你有帮助;希望这些提示能帮助你更好地理解和实现这个算法。如果有任何问题,请随时问我!