翻转数位题目解释和代码
这段代码的功能是计算一个32位整数中,经过至多一次位翻转(0变1或1变0)后能得到的连续1的最大长度。例如,输入1775
(二进制11011101111
),翻转中间的0后变为11011111111
,连续1的最大长度为8。
核心思路
代码通过维护两个变量cur
和insert
来跟踪当前连续1的长度和包含一次翻转的最长长度:
cur
:记录当前连续1的长度(遇到0时重置为0)。insert
:记录包含一次翻转的连续1的最大长度。每次遇到0时,insert
更新为cur + 1
(即把当前0翻转后的长度)。- 遍历每一位:检查每一位是0还是1,并更新
cur
和insert
的值,最终取最大值res
。
代码逐行解释
int reverseBits(int num) {int res = 0; // 最终结果:连续1的最大长度int cur = 0; // 当前连续1的长度int insert = 0; // 包含一次翻转的连续1的长度for (int i = 0; i < 32; ++i) // 遍历32位整数的每一位{if (num & (1 << i)) // 如果当前位是1{cur++; // 连续1的长度加1insert++; // 包含翻转的长度也加1}else // 如果当前位是0{insert = cur + 1; // 翻转当前0,长度为前面连续1的长度+1cur = 0; // 重置当前连续1的长度为0}res = max(res, insert); // 更新最大长度}return res;
}
关键逻辑分析
- 遇到1时:
cur
和insert
都加1,表示连续1的长度增加。
- 遇到0时:
insert
更新为cur + 1
,即假设翻转当前0后的总长度。cur
重置为0,因为当前连续1的序列被打断。
- 为什么有效?:
- 每次遇到0时,
insert
记录了“上一段连续1 + 当前翻转的0”的长度。 - 如果后续还有连续1,
insert
会继续累加,相当于“上一段连续1 + 翻转的0 + 新的连续1”。
- 每次遇到0时,
示例验证
输入num = 1775
(二进制11011101111
):
位: 1 1 0 1 1 1 0 1 1 1 1 0 ...(其余为0)
i 0 1 2 3 4 5 6 7 8 9 10 11...
cur 1 2 0 1 2 3 0 1 2 3 4 0...
ins 1 2 3 1 2 3 4 1 2 3 4 5...
res 1 2 3 3 3 3 4 4 4 4 4 5...最终res = 8(翻转第6位后的连续长度)
总结
这段代码巧妙地利用一次遍历,通过维护两个变量cur
和insert
,在线性时间内计算出翻转至多一位后的最长连续1的长度。其核心思想是动态更新包含一次翻转的最大长度,确保正确性的同时保持高效性。