前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >leetcode 190 Reverse Bits

leetcode 190 Reverse Bits

作者头像
流川疯
发布2019-01-18 14:50:05
3480
发布2019-01-18 14:50:05
举报

Reverse bits of a given 32 bits unsigned integer.

For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), return 964176192 (represented in binary as 00111001011110000010100101000000).

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

解决方案: Basically, this code is just keeping pop the last bit from n and push it to the end of the return result.

Do •Get last bit from n •Push the bit to the end of the result •Pop out the last bit of n

Until n is 0 •Push remaining 0s to the n by “ret << nShift”

•Return the result “ret”

代码语言:javascript
复制
 uint32_t ret = 0;

    int nShift = 32;
    while (n && nShift--)
    {
        // shift ret to left by one and move a room for the new push
        ret = (ret << 1);
        // Push the last bit of the n to ret
        if (n%2)
            ret |= 0x1;
        // pop the last element out
        n = (n>>1);
    }

    return ret << nShift; 

位操作详解

参考:http://www.crazycpp.com/?p=82

我们先来看看位运算操作符:& (按位与)、| (按位或)、^ (按位异或)、~ (按位取反)、>> (按位右移)、<< (按位左移)。

1、&(按位与) 从概念上来讲,就是将参与运算的两个分量对应的每一位来做逻辑与运算,若两者都为真(等于1),则结果才为真(等于1)。否则都为假(等于0)。 即:1 & 1 = 1 、1&0 = 0 、0&1 = 1、0&0 = 0 这里我们先来看看那一个8位二进制的例子: 7&8 = 0000 0111 & 0000 1000 = 0000 0000 = 0 7&6 = 0000 0111 & 0000 0110 = 0000 0110 = 6

2、| (按位或) 即把参与运算的每个分量对应的每一位来做逻辑或运算,即两者都为假(为0)时,才为假(为0),否则皆为真。 即:0|0 = 0、1|0 = 1、0|1 = 1、1|1 = 1 来看看8位二进制的例子: 7|8 = 0000 0111 | 0000 1000 = 0000 1111 = 15 7|6 = 0000 0111 | 0000 0110 = 0000 0111 = 7

3、^(按位异或) 即把参与运算的每个分量对应的每一位来做异或运算,即两者相同为假,不同为真。 即:0|0 = 0、 1|0 = 1、0|1 = 1、 1|1 = 0 看下面的例子: 7^8 = 0000 0111 ^ 0000 1000 = 0000 0111 = 7 7^6 = 0000 0111 ^ 0000 0100 = 0000 0011 = 3

4、~(按位取反) 即把二进制位的每一位进行取反运算,简而言之就是1变成0,0变成1。 直接看例子: ~7 = ~0000 0111 = 1111 1000 = 248

5 >>(按位右移)把二进制位整体向右移动。 7>>1 = 0000 0111 >> 1 = 0000 0011 = 3 7>>2 = 0000 0111 >> 2 = 0000 0001 = 1 这里右移等于除了2的N次方,N为右移的位数。

6 <<(按位左移)这里就不详细说了,和右移相反。

位操作应用

好了,下面讲讲实际应用吧。 一、一种颜色的表示方式—- 通过DWORD来表示颜色 定义:typedef unsigned long DWORD; 即为一个无符号32位(32机器)长整数,有四个字节,我们从左到右叫他1,2,3,4字节,每一个字节的范围是0~255。第一个字节表示alpha值,即透明度。如果是255,表示不透明,0表示完全透明(

看不到),其他分别是R,G,B值。 可通过下列方法获得每个字节的值: int A = (int)((DWORD & 0xFF000000) >> 24); int R = (int)((DWORD & 0x00FF0000) >> 16); int G = (int)((DWORD & 0x0000FF00) >> 8); int B = (int)(DWORD & 0x000000FF);

DWORD dwColor = (A<<24)+(R<<16)+(G<<8)+B; 有了前面的基础,我相信大家对上面的换算方法,一看就明白吧。如果对16进制不敏感的童鞋,可以用计算机把十六进制换算成二进制,更容易理解。

二、状态系统中的使用

在游戏开发中,我们通常用一个32位(假设这里用32位)的整数来存储角色的状态(这样做主要是为了节约存储空间,同时也减小网络同步消息包的size)。所谓的状态,就是大家熟悉的Buff或者DeBuff。 enum ROLE_STATUS { STATUS_NORMAL = 0, // 正常 STATUS_DIE = 1, // 死亡状态 STATUS_GOD , // 无敌 STATUS_DISAPPEARING , // 消失中状态 STATUS_DEF_ADJUST , // 物理防御提升/降低 STATUS_MDEF_ADJUST , // 魔法防御提升/降低 STATUS_ATK_CRI_ADJUST , // 同时提升物理攻击和爆击率 STATUS_MAXHP_ADJUST , // HP上限调整 STATUS_MAXMP_ADJUST , // MP上限提升/降低 //…… 这里最多只能写32个,因为我们假设是用32位数据来存储状态。 };

状态数据定义好了,现在来看看怎么使用他们。 首先, 角色上线,我要给他一个保护状态,应该这样操作。 DWORD dwRoleStatus = STATUS_GOD; 同时,角色使用了一个物品,这个物品的效果时,HP和MP上限增加一段时间。因此要附加调整玩家的HP和MP上限的状态,应该这样。 DWORD dwRoleStatus |= (STATUS_MAXHP_ADJUST+STATUS_MAXMP_ADJUST); 这里是|=而不是=操作,因为不能清掉之前附加的无敌保护状态。所以用或运算。 该角色受到其他玩家或者怪物的攻击,我们要判断被攻击的这个角色的受保护状态状态还在不在。执行如下逻辑 if( dwRoleStatus & STATUS_GOD ) // 判断位是否为1 { // 受保护状态,不能被攻击 }

接下来,角色无敌保护时间过期了,我们要清除无敌状态,执行如下操作 dwRoleStatus &= ~STATUS_GOD; 这里用到了取反的计算。~STATUS_GOD的结果是第二位为0外,其他都为1。然后和dwRoleStatus做按位与计算。 STATUS_GOD 等于 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010; ~STATUS_GOD 等于 1111 1111 1111 1111 1111 1111 1111 1111 1111 1101; 因此和dwRoleStatus相与之后,dwRoleStatus除了第二位以外的位,都保留下来了。第二位不管是什么值,都会被设置为0,这样子就把STATUS_GOD这个状态清除掉了。同理我们要清除多个状态的时候,先把要清楚的状态或运算到一起。再取反,然后和dwRoleStatus按位与。起到同时清除多个状态。

然后讲讲异或,它有一个性质是,两次异或,能还原回来

例如 a=7,b=6;

a = a^b^b

我们来看看那二进制的操作

a = 0111

b = 0110

c = a^b = 0001

a = c^b = 0111

写到这里,想到一道经典的C++笔试题,即不需要第3个变量,交换两个变量的值。

a = a^b = 0001

b = b^a = 0111

a = a^b = 0110

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年05月04日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档