3228.将1移动到末尾的最大操作次数

目标

给你一个 二进制字符串 s。

你可以对这个字符串执行 任意次 下述操作:

  • 选择字符串中的任一下标 i( i + 1 < s.length ),该下标满足 s[i] == '1' 且 s[i + 1] == '0'。
  • 将字符 s[i] 向 右移 直到它到达字符串的末端或另一个 '1'。例如,对于 s = "010010",如果我们选择 i = 1,结果字符串将会是 s = "000110"。

返回你能执行的 最大 操作次数。

示例 1:

输入: s = "1001101"
输出: 4
解释:
可以执行以下操作:
选择下标 i = 0。结果字符串为 s = "0011101"。
选择下标 i = 4。结果字符串为 s = "0011011"。
选择下标 i = 3。结果字符串为 s = "0010111"。
选择下标 i = 2。结果字符串为 s = "0001111"。

示例 2:

输入: s = "00111"
输出: 0

说明:

  • 1 <= s.length <= 10^5
  • s[i] 为 '0' 或 '1'。

思路

有一个二进制字符串 s,每次操作可以选择一个下标 i,满足 s[i] == '1's[i + 1] == '0',将 s[i] 向右移直到遇到另一个 1 或者到达末尾,返回可以执行的最大操作次数。

要使操作次数最大,每组相邻的 0 都要为其前面的 1 提供一次操作。换句话说操作尽量不要让右侧的 0 过早的合并,累加每组相邻的 0 前面 1 的个数即可。

计算前缀 1 个数,正序遍历,第一次遇到 0 时,就加上前面 1 的个数,跳过相邻的 0(因为每次操作都要移到最右侧,相邻的 0 对每个 1 只能贡献一次操作)。

代码


/**
 * @date 2025-11-13 8:44
 */
public class MaxOperations3228 {

    public int maxOperations(String s) {
        int n = s.length();
        char[] chars = s.toCharArray();
        int[] prefix = new int[n + 1];
        int res = 0;
        for (int i = 1; i <= n; i++) {
            prefix[i] = prefix[i - 1] + (chars[i - 1] - '0');
        }
        int i = 0;
        while (i < n) {
            if (chars[i] == '0') {
                res += prefix[i];
            }
            while (i < n && chars[i++] == '0') {
            }
        }
        return res;
    }

}

性能

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注