题目描述#
欸,这题听着就带感——颠倒给定的 32 位整数的二进制位。也就是说,把这个数当成一串 32 位的 0/1,然后整串首尾翻转:原来的第 0 位变成第 31 位,第 1 位变成第 30 位,以此类推,再把翻转后的二进制读成一个新数返回。
思路#
咱第一眼看,这题的关键词是"逐位搬运"。既然要把低位翻到高位,那就一位一位地从 n 的最低位取出来,塞到答案 ans 的最低位,再让 ans 整体左移腾位置——这样最先取出的位会被一路顶到最高位去,正好实现了翻转。
具体每一轮干两件事:
ans = ans<<1 | (n & 1):先把ans左移一位(原来的内容整体往高位挪、最低位空出来),再用n & 1取出n当前的最低位,用按位或|填进那个空位。n = n >> 1:把n右移一位,让下一位变成新的最低位,等着下一轮被取走。
循环正好 32 次,对应 32 个二进制位。本姑娘画个小账本帮你记:第 1 轮取到的是 n 的最低位,但它被后面 31 次左移一路抬到了第 31 位(最高位);最后一轮取到的是 n 的最高位,落在第 0 位(最低位)——首尾就这么对调过来啦,干净利落!
ans <<= 1 和 ans | bit 的先后顺序也有讲究:必须先左移、再或入新位,要是反了,新位就会被下一次左移又顶走一格,全乱套。
知识边界#
- 取最低位:
n & 1拿到二进制最末位(0 或 1),是逐位处理的标配手法。 - 右移送位:
n >> 1丢掉已处理的最低位,把下一位推到末尾。这里题目语境是无符号的 32 位,每位非 0 即 1,不必纠结符号位。 - 左移腾位 + 或入:
ans = ans<<1 | (n&1)是"反转/收集二进制位"的经典组合,先移后或的顺序不能调换——容易踩坑哦。 - 固定循环 32 次:位宽是题目写死的 32,所以循环次数是常数,时间复杂度 $O(1)$(与数值大小无关)。
- 运算符优先级:Go 里
<<优先级高于|,所以ans<<1 | (n & 1)等价于(ans<<1) | (n&1),不加括号也对;但给n & 1套个括号读起来更稳妥。
代码#
这段咱也原样保留,循环 32 次逐位搬运:
func reverseBits(n int) int {
ans := 0
for i := 0; i < 32; i++ {
ans = ans<<1 | (n & 1)
n = n >> 1
}
return ans
}好啦,位运算这个新章节就先开这两道~咱去整理今天的照片咯,下次再来收拾更刁钻的位操作题!