190. 颠倒二进制位

题目描述

在这里插入图片描述

思路一

用一个变量res存储结果, 依次得到要转换数字的低位,然后保存在res中,res每得到一位后进行左移腾出一位用来保存下一位。
一个例子

原数字 1011 ,res = 0
    
res 左移一位,res = 0,
得到 1011 的最低位 1 加过来, res = 1
1011 右移一位变为 101
    
res = 1 左移一位,res = 10,
得到 101 的最低位 1 加过来, res = 11
101 右移一位变为 10 
    
res = 11 左移一位,res = 110,
得到 10 的最低位 0 加过来, res = 110
10 右移一位变为 1 
    
res = 110 左移一位,res = 1100,
得到 1 的最低位 1 加过来, res = 1101
1 右移一位变为 0, 结束 
func reverseBits(num uint32) uint32 {
    var res uint32 = 0
    fosr i := 0;i < 32; i++ {
        res <<= 1
        res |= (num & 1)
        num >>= 1
    }
    return res
}

思路二

采用分治的思路。
如果两位数字,怎么逆序?比如2 4,我们只需要交换两个数字,得到4 2
如果是四位数字,怎么逆序?比如1 2 3 4,我们可以交换两部分1 23 4,变成3 4 1 2,接下来分别对3 41 2分别逆序,两位数的逆序我们已经知道怎么做了。
如果是八位数字,怎么逆序?比1 2 3 4 5 6 7 8,同样的我们只需要交换两部分1 2 3 45 6 7 8 的数字,变成 5 6 7 8 1 2 3 4,接下来只需要分别将两部分5 6 7 81 2 3 4 分别逆序,四位数的逆序已经讨论过。

如上,我们也可以通过这种思路去解决32位的数字,32位左半部分和右半部分交换,得到两个16位的数字,在分别对16位的数字交换,得到8位的数字。。。
一个例子

原始32位:Abcdefghijklmnop qrstuvwxyz012345
第一步:qrstuvwx yz012345 Abcdefgh ijklmnop
第二步:yz01 2345 qrst uvwx ijkl mnop Abcd efgh
第三步:23 45 yz 01 uv wx qr st mn op ij kl ef gh Ab cd
第四步:45 23 01 yz。。。。。。。。。。。。。。。。。cd Ab
第五步:5 4 3 2 。。。。。。。。。。。。。。。。。。。。。b A

思路我们有了,那么现在怎么交换二进制的两部分呢?
在二进制中交换两部分,可以用一个技巧,举个例子,对于x = 1101交换两部分,我们只需要((1100) & x )>>> 2 | ((0011) & x) <<< 2 = (0011)|(0100)= 0111,然后就完成了 1101 的交换。

func reverseBits(num uint32) uint32 {
    num = ((num & 0xffff0000) >> 16) | ((num & 0x0000ffff) << 16)
    num = ((num & 0xff00ff00) >> 8) | ((num & 0x00ff00ff) << 8)
    num = ((num & 0xf0f0f0f0) >> 4) | ((num & 0x0f0f0f0f) << 4)
    num = ((num & 0xcccccccc) >> 2) | ((num & 0x33333333) << 2)
    num = ((num & 0xaaaaaaaa) >> 1) | ((num & 0x55555555) << 1)
    return num
}

本质上,2 4 8位换位本质实在讲一种换法,这种换法本质是错位法 即创造两个互相错位的数据 这样保证数据不会丢失,下面用数字解释:

先屏蔽 再移位
比如要创造4位错位, 即12345678换位56781234, 那么先屏蔽5678得到12340000,移位得到00001234, 同理可得56780000, 再加起来得到56781234;
然后再2位错位, 即屏蔽得到56001200,移位得到00560012, 同理可得78003400, 加起来得到78563412;
再创造一位错位,即先屏蔽得到70503010,移位得到07050301, 同理可得80604020, 加起来就是最后结果即87654321.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值