题目描述

2027. 转换字符串的最少操作次数

给定仅包含 X 和 O 的字符串 s。每次选择字符串内三个连续位置,把这些位置全部变成 O,原本是 O 的位置保持不变。返回使整个字符串都变为 O 所需的最少操作次数。

示例 1:

输入:s = "XOXXOX"
输出:2
解释:处理下标 0…2 和 3…5 两个区间即可。

示例 2:

输入:s = "OOX"
输出:1
解释:选择整个字符串,将最后一个 X 变成 O。

示例 3:

输入:s = "OOOOO"
输出:0
解释:已经没有 X,无需操作。

提示:

  • 3 ≤ s.length ≤ 1000。
  • s 仅由 X 和 O 组成。
  • 每次选择恰好三个连续位置,区间不能超出字符串范围。

题意分析

每次必须选择字符串内恰好三个连续位置,将它们全部置为 O,求消除所有 X 的最少操作次数。区间里原有的 O 可以一起处理,不会产生任何副作用。

这是覆盖所有待处理 X 的问题,不是翻转字符,也不要求每次选中的三个位置原本都是 X。每次操作的实际区间必须在字符串内,题目保证长度至少为三。

解法:从最左未处理 X 开始覆盖

核心思路

[!blue]

从左向右扫描,保持当前位置之前的所有 X 都已被此前操作覆盖。遇到 O 不需要付出操作,直接前进;遇到最左侧尚未覆盖的 X,任何完整方案都必须至少有一次操作覆盖它。

设这个位置为 i。覆盖它的长度三区间,起点不能在 i 的右侧。既然左边已经处理完成,就应让这次操作尽量向右伸展,使它顺便覆盖最多的后续位置,而不是把覆盖机会浪费在更左侧。

这个选择不会增加最优次数:把某个覆盖 i 的操作向右平移到最靠右的合法位置,失去的覆盖只位于已经处理好的左侧,i 及原先覆盖的更右目标都不会漏掉。这样可以让一个最优方案包含当前贪心操作,再继续处理未覆盖后缀。

通常区间是 [i, i + 2],所以计数加一后可直接令 i += 3。若 i 已靠近末尾,实际选择最后三个位置 [n - 3, n - 1],同样覆盖全部剩余字符。程序只求次数,无需真正修改字符串,跳到末尾之外表示剩余部分已经处理完,并不是执行越界操作。

解题步骤

  1. 从下标零开始,操作数初始化为零。
  2. 当前字符为 O 时前进一步。
  3. 当前字符为尚未覆盖的 X 时,计一次操作,并将扫描位置前移三格。
  4. 扫描结束返回次数;末尾不足三格时,实际操作区间向左贴齐字符串末端。

代码实现

class Solution {
    public int minimumMoves(String s) {
        int answer = 0;

        for (int i = 0; i < s.length(); ) {
            if (s.charAt(i) == 'X') {
                answer++;
                i += 3;
            } else {
                i++;
            }
        }

        return answer;
    }
}
func minimumMoves(s string) int {
    answer := 0
    for i := 0; i < len(s); {
        if s[i] == 'X' {
            answer++
            i += 3
        } else {
            i++
        }
    }
    return answer
}

复杂度分析

  • 时间复杂度:$O(n)$,扫描下标只向右移动,不回头处理已覆盖字符。
  • 空间复杂度:$O(1)$,只记录扫描位置与操作数,原字符串不修改。

关键点总结

[!green]

  • 最左未覆盖的 X 强制至少一次操作,尽量向右覆盖不损失已经处理的目标。
  • 一次操作可以覆盖多个 X,也可以包含原本已经正确的 O。
  • 跳过三个位置表达已经覆盖的区间,无需逐字符改写。
  • 末尾采用贴齐边界的合法区间,计数逻辑仍保持一致。

易错点总结

[!yellow]

  • 每看到一个原始 X 就加一次,忽略它可能已被前一次操作覆盖。
  • 只处理连续三个 X,遗漏区间中允许包含 O 的规则。
  • 把操作当成翻转,担心覆盖旧 O 会变坏,错误限制了可选区间。
  • 最后不足三个位置就放弃,实际可以将区间左移到最后三个位置,仍只需一次。
  • 将代码跳到数组末尾之外理解为实际区间也可以越界,混淆了计数扫描与操作位置。

相似题目

题目 难度 关联与区别
995. K 连续位的最小翻转次数 困难 同样从最左未处理位置决定覆盖操作,原题翻转会影响后续状态,本题直接置 O 且窗口长度固定为 3。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/4020321253
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!