关于二进制字符串翻转算法核心思路的技术疑问
问题描述
给定仅包含"0"和"1"的二进制字符串s,以及包含两类操作的查询数组query:
- "Count":返回字符串中"1"的数量;
- "Flip":翻转子串
[0, idx](0与1互转),idx为字符串首个"0"的索引,返回idx(调用时保证存在至少一个"0")。
约束:1 ≤ s.length() ≤ 1e5,1 ≤ query.length ≤ 1e5。
现有算法思路提出将s前32位转为十进制数以优化操作,针对该思路的核心步骤存在以下疑问:
- 如何得出「翻转仅会影响字符串前32位」的结论?
- 公式
2^32-1 - int(S[0:32][::-1])的设计逻辑是什么? - 为何能判定「剩余子串S[32:]不会再发生变化」?
问题解答
1. 翻转仅影响前32位的原因
Flip操作的核心是每次翻转从开头到第一个0的位置idx的子串,分两种情况分析:
- 如果前32位中存在0,第一个0的位置
idx必然在前32位范围内,翻转操作只会涉及前32位,不会触及后续部分; - 只有当前32位全为1时,第一个0才会出现在
S[32:]中,此时执行Flip会翻转到该位置,但翻转后前32位会变成全0(原全1翻转后全0)。接下来的Flip操作会从位置0开始,逐个处理前32位里的0,直到前32位再次变回全1——这个过程最多需要32次操作,且所有操作的idx都在前32位内,不会碰S[32:]。
简言之,最多只会有一次Flip操作触及S[32:],之后所有翻转都只影响前32位,这也是该优化思路的核心依据。
2. 公式2^32-1 - int(S[0:32][::-1])的设计逻辑
这个公式用于快速计算前32位全翻转后的整数值,拆解来看:
S[0:32][::-1]:将前32位字符串反转。因为字符串左到右对应二进制的高位到低位,反转后能让字符串的第i位对应整数的第i个二进制位(最低位为第0位),转成整数时位权对应才正确;2^32-1是32位全1的二进制数(如十进制的4294967295)。用它减去反转后的前32位整数,等价于对每一位取反(0变1,1变0)——因为全1数的每一位减去原数对应位,结果正好是原位的取反。
该公式能在O(1)时间内完成前32位的全翻转计算,无需逐位处理,大幅提升效率。
3. 剩余子串S[32:]不会再变化的原因
结合第一个问题的分析:
- 第一次触及
S[32:]的Flip操作会把该位置的0翻转为1,同时前32位变为全0; - 后续操作集中处理前32位,直到前32位再次变为全1。如果此时
S[32:]还有0,会再次触发触及S[32:]的Flip,但这次翻转会把之前被改动的S[32:]位置再次翻转(相当于恢复原状),同时前32位又变为全0; - 如此循环,
S[32:]的每一位被翻转的次数必然是偶数次,最终会回到初始状态。因此从长期来看,S[32:]的有效状态不会有净变化,可以预先计算其初始的1的数量,后续无需再修改。
内容的提问来源于stack exchange,提问作者meallhour
相关产品推荐
相关产品推荐

