【LeetCode - Java】190. 颠倒二进制位 (简单)

1. 题目描述

在这里插入图片描述

2. 解题思路

题目明确这是二进制位的运算,那么我们就得从常数转换为二进制入手。最常规的方法,把常数除二取余然后直接乘对应的位权,完事了。对于C语言来说,确实是这样子的,因为在C语言当中有无符号常数uint32,但在Java语言当中就没那么顺利了。C语言几行代码可以搞定的逻辑,在Java中则需要分情况讨论,因为32位的二进制数,若最高位为1时表示的是负数(这里涉及原码、反码和补码的知识),但在本题的含义中却是不能够看成负数的,因此需要对这个假负数进行转换,把它的最高位置0(颠倒前的最高位相当于颠倒后的最低位,因此颠倒后要加1)后才可以与正数一样进行相关运算。

上述的方法时间性能到了100%,我以为这已经是属于好的方案了,然而官解中全都是一些位运算,实属让人恶心。但也没办法,还是得啃一啃,其实就是把十进制转二进制过程中的除二取余法替换成了直接的位移运算,可以从前往后进行或从后往前进行。

官解中还有一种分治的写法,但个人认为可读性极差,这里不作相关解读了。

3. 代码实现

3.1 数值运算(C语言版)

uint32_t reverseBits(uint32_t n) {
    uint32_t sum = 0;
        for (int i = 0; i < 32; i++) {
            sum *= 2;
            sum += n % 2;
            n /= 2;
        }
    return sum;
}

在这里插入图片描述

3.2 数值运算

public int reverseBits(int n) {
        if (n < 0) {
            n = n << 1;
            n = n >>> 1;
            return compute(n) + 1;
        }
        return compute(n);
    }

    public int compute(int n) {
        int sum = 0;
        for (int i = 0; i < 32; i++) {
            sum *= 2;
            sum += n % 2;
            n /= 2;
        }
        return sum;
    }

这个代码相比于C语言实在太臃肿了,没办法,谁叫咋们Java没有uint32呢!
在这里插入图片描述

3.3 二进制运算逐位逆转

public int reverseBits(int n) {
        int sum = 0;
        for (int i = 0; i < 32; i++) {
            // 从前往后
            sum += (n << i >>> (31 - i)) & 1 << i;
            // 从后往前
//            sum += n & 1 << 31 - i;
//            n = n >>> 1;
        }
        return sum;
    }

从前往后:
在这里插入图片描述
从后往前:
在这里插入图片描述

3.3 对比

其中最终的结果对比也是让我大吃一惊的,用运算的解法时间消耗居然比数值运算还要,不过空间消耗倒是优化了挺多。两种算法都是常数级的时间复杂度O(1),而空间复杂度也同样是O(1)
在这里插入图片描述

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

Beeemo

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值