LeetCode 190. Reverse Bits

题目

Reverse bits of a given 32 bits unsigned integer.

Example 1:

Input: 00000010100101000001111010011100
Output: 00111001011110000010100101000000
Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.

Example 2:

Input: 11111111111111111111111111111101
Output: 10111111111111111111111111111111
Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10101111110010110010011101101001.

Note:

  • Note that in some languages such as Java, there is no unsigned integer type. In this case, both input and output will be given as signed integer type and should not affect your implementation, as the internal binary representation of the integer is the same whether it is signed or unsigned.
  • In Java, the compiler represents the signed integers using 2's complement notation. Therefore, in Example 2 above the input represents the signed integer -3 and the output represents the signed integer -1073741825.

Follow up:

If this function is called many times, how would you optimize it?


这道题就是反转一个二进制数字,常规操作就是每次取出第一个和最后一个数进行交换,或者每次取出第一个或最后一个数,并把它倒着塞到一个新二进制数中。


2023.4.9 Java

这题踩坑了……首先是老实巴交地一个个shift bit的方法,踩了以下几个坑:

1. 虽然右移是>>>(unsigned,signed是>>),但左移是<<,啊!没有研究为啥是这样,有人说>>>是logical right shift,那就>>是arithmetic right shift?但对于左移来说好像是一样的。

2. 不能像191一样while (n != 0),必须得for (int i =0; i < 32; i++),也是没有研究为啥……

嗯,代码如下:

public class Solution {
    // you need treat n as an unsigned value
    public int reverseBits(int n) {
        int result = 0;
        for (int i = 0; i < 32; i++) {
            int bit = n & 1;
            result = (result << 1) + bit;
            n = n >>> 1;
        }
        return result;
    }
}

然后就是另一个最优解之O(1)的骚操作,就是底下之前记了笔记的最后一种方法。(梦回data lab是真的)但是懒得好好想了,就抄了答案……

https://leetcode.com/problems/reverse-bits/solutions/1232842/java-c-0ms-o-1-time-complexity-in-place-detailed-explanation/ 

public class Solution {
    // you need treat n as an unsigned value
    public int reverseBits(int n) {
        n = ((n & 0xffff0000) >>> 16) | ((n & 0x0000ffff) << 16);
        n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8);
        n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4);
        n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2);
        n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1);
        return n;
    }
}

用API,就是:Integer.reverse(n)


2019.6.6 C++
第一种操作需要用到之前写密码学作业时用过的bitset,都忘了这个数据结构的存在了,用起来还是非常方便的。代码如下,时间4ms,90.14%,空间8.2M,6.62%:

/*
 * @lc app=leetcode id=190 lang=cpp
 *
 * [190] Reverse Bits
 */
class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
        bitset<32> bits(n);

        for (int i = 0; i < 16; i++) {
            bool left = bits[i];
            bits[i] = bits[31 - i];
            bits[31 - i] = left;
        }
        return (uint32_t) bits.to_ulong();
    }
};

第二种操作就是纯位运算了,结果数result是从左往右拿到,原始输入n是从右往左获取,每次获取一个n最右边的数就把它塞到result中。代码如下,时间4ms,90.14%,空间8.1M,34.74%:
 

/*
 * @lc app=leetcode id=190 lang=cpp
 *
 * [190] Reverse Bits
 */
class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
        uint32_t result = 0;
        for (int i = 0; i < 32; i++) {
            result <<= 1;
            result |= n & 1;
            n >>= 1;
        }
        return result;
    }
};

最后还有一种精妙绝伦的骚操作,有点类似于归并的思想,通过整组调换顺序完成。举个例子,假如输入是ABCDEFGH,那么想让它变成倒序,可以这么做:
ABCDEFGH -> EFGHABCD(四个一组) -> GHEFCDAB(两个一组) -> HGFEDCBA(一个一组)

/*
 * @lc app=leetcode id=190 lang=cpp
 *
 * [190] Reverse Bits
 */
class Solution {
public:
    uint32_t reverseBits(uint32_t n) {
        int result = (n >> 16) | (n << 16);
        result = ((result & 0xff00ff00) >> 8) | ((result & 0x00ff00ff) << 8);
        result = ((result & 0xf0f0f0f0) >> 4) | ((result & 0x0f0f0f0f) << 4);
        result = ((result & 0xcccccccc) >> 2) | ((result & 0x33333333) << 2);
        result = ((result & 0xaaaaaaaa) >> 1) | ((result & 0x55555555) << 1);
        return result;
    }
};


代码如下,时间复杂度O(1),0ms,100%,空间8.1M,39.12%:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值