[LeetCode] 1375. Number of Times Binary String Is Prefix-Aligned 二进制字符串前缀一致的次数


You have a 1-indexed binary string of length n where all the bits are 0 initially. We will flip all the bits of this binary string (i.e., change them from 0 to 1) one by one. You are given a 1-indexed integer array flips where flips[i] indicates that the bit at index flips[i] will be flipped in the ith step.

A binary string is prefix-aligned if, after the ith step, all the bits in the inclusive range [1, i] are ones and all the other bits are zeros.

Return the number of times the binary string is prefix-aligned during the flipping process.

Example 1:

Input: flips = [3,2,4,1,5]
Output: 2
Explanation: The binary string is initially "00000".
After applying step 1: The string becomes "00100", which is not prefix-aligned.
After applying step 2: The string becomes "01100", which is not prefix-aligned.
After applying step 3: The string becomes "01110", which is not prefix-aligned.
After applying step 4: The string becomes "11110", which is prefix-aligned.
After applying step 5: The string becomes "11111", which is prefix-aligned.
We can see that the string was prefix-aligned 2 times, so we return 2.

Example 2:

Input: flips = [4,1,2,3]
Output: 1
Explanation: The binary string is initially "0000".
After applying step 1: The string becomes "0001", which is not prefix-aligned.
After applying step 2: The string becomes "1001", which is not prefix-aligned.
After applying step 3: The string becomes "1101", which is not prefix-aligned.
After applying step 4: The string becomes "1111", which is prefix-aligned.
We can see that the string was prefix-aligned 1 time, so we return 1.

Constraints:

  • n == flips.length
  • 1 <= n <= 5 * 10^4
  • flips is a permutation of the integers in the range [1, n].

这道题给了一个长度为n的二进制字符串,初始化均为 '0',然后又给了一个 flips 数组,每次翻转 flips[i] 位置的字符。然后定义了一个前缀一致的概念,即在第i步时,若范围 [1, i] 内的字符全是 '1',且其他位上均为 '0'。然后问在翻转的过程中,会出现前缀一致的次数。这道题博主最新想到的方式其实是位操作 Bit Operation,因为是需要翻转二进制的位,很自然的联想到用 “亦或” 操作,只要 “亦或“ 个1,就可以翻转位了。然后验证前缀一致也可以用右移操作来进行,这里我们不用字符串,而是用一个真实的二进制数,比如验证 11110 的话,就是验证前四位是否都是1,那么只要把 11110 右移1位,然后看是不是等于 2^4 - 1 就可以了。写完代码后,博主很有信心的 submit 了,结果发现会有 failed case,原来给的 test case 的n可能很大,远超整型数的 32 位,长整型的 64 位,后来定睛一看,题目中已经限定了n的范围是 [1, 50000],所以位操作的平移肯定不行,只得另辟蹊径。

既然位操作不行,那还是用字符串吧,就建立一个长度为n的字符串,然后按步骤进行翻转吧,也没什么难度。无非就是要验证字符串的前i个字符是否都为 ‘1’ 嘛,直接用 substr 来取字串就行了,然后判断是否都是 ‘1’ 即可。满心期待以为这次绝对过了,结果发现 Memory Limit Exceeded (MLE) 了,内存使用超标了。连新建长度为n的字符串都不允许,这是博主万万没想到的,那么这道题一定存在很 tricky 的解法,得好好分析一下。博主刚开始以为 flips 里的数组是任意数字,可能会出现重复数字,但是仔细看了下题目的限制条件,发现 flips 数组里面是 [1, n] 中的全排列,即不会有重复数字。这样的话,当前缀一致出现的时候,则范围内 [1, i] 内的数字都会出现,可能顺序不同,那么一个简单直接的判断方法就是求和,只要数字和跟 [1, i] 中的数字和相同,就一定是前缀一致。这里使用两个变量 sum 和 target,遍历 flips 数组,翻转第 flips[i-1] 个数字时候,把 flips[i-1] 加到 sum 中,把i加到 target 中,如果 sum 和 target 相等,则说明前缀一致了,res 自增1即可,参见代码如下:


解法一:

class Solution {
public:
    int numTimesAllBlue(vector<int>& flips) {
        int n = flips.size(), res = 0, sum = 0, target = 0;
        for (int i = 1; i <= n; ++i) {
            sum += flips[i - 1];
            target += i;
            if (sum == target) {
                ++res;
            }
        }
        return res;
    }
};

实际上我们并不需要计算数字之和,只需要统计需要翻转的位置中最大的值 curMax,如果这个最大值正好等于当前的遍历位置i,则说明前缀一致出现了,这也不难理解,因为当遍历到位置i时,说明此时总共翻转了i个数字,且每个翻转的位置中最大的数字就是i,则说明i位置之前的每个数字有且只出现了一次,即所有数字都翻转成1了,即前缀一致的情况,参见代码如下:


解法二:

class Solution {
public:
    int numTimesAllBlue(vector<int>& flips) {
        int n = flips.size(), res = 0, curMax = 0;
        for (int i = 1; i <= n; ++i) {
            curMax = max(curMax, flips[i - 1]);
            if (curMax == i) ++res;
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1375


类似题目:

Bulb Switcher

Bulb Switcher II


参考资料:

https://leetcode.com/problems/number-of-times-binary-string-is-prefix-aligned

https://leetcode.com/problems/number-of-times-binary-string-is-prefix-aligned/solutions/532538/javacpython-straight-forward-o1-space-by-egzx/


LeetCode All in One 题目讲解汇总(持续更新中...)

posted @ 2026-08-29 11:01  Grandyang  阅读(2)  评论(0)    收藏  举报
Fork me on GitHub