IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 关于位运算的几种常见题型分析 -> 正文阅读

[数据结构与算法]关于位运算的几种常见题型分析

有不少人对位运算感到陌生,一是因为我们不习惯用二进制的形式来进行计算,二是我们遇到的题目较少,并且很不熟练。可能我们遇到数组、链表等常见数据结构类的问题时做起来很顺利,哪怕是中等或者困难的题目也能完成,但是遇到关于位运算的简单题目却无从下手,下面我将分析几道leetcode上面的几道简单且经典的位运算题目,供大家做参考。

在分析题目之前,我先带大家熟悉下位运算的几种常见符号。

&:按位与运算。同1为1,否则为0。例:0&0=0;0&1=0;1&0=0;1&1=1;

|: 按位或运算。有1为1, 没1为0。 例:0|0=0;? 0|1=1;? 1|0=1; 1|1=1;

^: 按位异或运算。相异为1,相同为0。例:0^0=0;? 0^1=1;? 1^0=1; 1^1=0;

~:取反运算。 ~1=0;~0=1;

<<:左移运算符。左边的二进制位丢弃,右边补0。例:1011 左移一位后变为 10110;左移几位? ? ? ? ? ? 就是乘2^n次方。

>>:右移运算符。正数左补0,负数左补1,右边丢弃。例:1011 右移一位后变为101,最后一位? ? ? ? ? 丢弃;右移几位就是除2^n次方。

(1)给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回false 。如果存在一个整数 x 使得?n =?2^x?,则认为 n 是 2 的幂次方。

?通过分析题目,我们首先发现可以让n这个数一直除2,直到最后看是否等于1或者等于0,这不就是递归吗,我们可以很容易的写出递归的代码,代码如下:

class Solution {
public:
    bool isPowerOfTwo ( int n )
    {        
         //递归终止条件,如果n=1则返回true,2^0=1;
         if ( n == 1 )
             return true;
         if ( n == 0 )  
             return false;

         //如果n为偶数的话,则递归遍历
         if ( n % 2 == 0 )
             return isPowerOfTwo ( n / 2 );
         //否则是奇数,返回false
         else 
             return  false;
    }
};

但我们怎么利用位运算来解决本道题呢,我们通过举例发现:8的二进制形式为1000,而7的二进制形式为0111,如果题目输入的n是8的情况时,显然是返回true的。我们套用上面的按位运算,发现当8和7进行按位与运算时,最终答案竟然是0。再带入其他数字,例如16的二进制数为10000,而15的二进制数为01111,两者按位与运算同样是0。所以可以得出规律,二的倍数和二的倍数减一的按位与运算结果为0,我们得到如下代码。

class Solution {
public:
    bool isPowerOfTwo ( int n )
    {        
         //如果n为1时返回true
         if ( n == 1 )
            return true;
         if ( n < 1 )
            return false;
         //返回n&n-1的结果,如果为0则为true,否则返回false
         //特别提示:&的优先级要小于==的优先级,所以&的两边要加上括号
         return ( n & ( n - 1 ) == 0;
    }
};

(2)编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数

此题同样要使用二进制位运算来解题,下面给出第一种写法:可以发现当让n&(n-1)时,n的最低位的1会变为0,我们利用这个特性,可以让n不停的和n-1进行与运算,直到n为0,下面给出我们的代码:

class Solution {
public:
    int hammingWeight ( uint32_t n )
    {        
         //用res来记录为1的个数
         int res = 0;
         //当n不为0时,一直循环
         while ( n )
         {
              //将n的最低位的1变为0,同时res加1
              n = n & ( n - 1 );
              res++;
         }
         return res;
    }
};

?我们也可以每次找到最低位的1以后,再将二进制代码右移一位,即删除掉那个1,然后依次循环上述过程,找到所有的1,下面给出代码:

class Solution {
public:
    int hammingWeight ( uint32_t n )
    {        
         //用res来记录为1的个数
         int res = 0;
         //因为n是32位,所以需要循环32次,每次左移一位
         for ( int i = 0; i < 32; i++ )
         {
                //如果最后一位和1相与的结果是1,则说明最后一位为1,res+1
                if ( ( n & 1 ) == 1 )
                    res++;
                //无论最低为是否为1都需右移一位
                n >>= 1;
         }
                return res;
    }
};

(3)给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

我看到这题,第一时间想到的是哈希表法,但是题目规定了时间复杂度为线性的,所以我们只能考虑位运算来解决。

回顾异或运算,我们发现异或运算有三个特性:

1、异或运算满足结合律和交换律。例:a^b^c=c^b^a=a^(b^c);

2、任何数和自身进行异或运算都为0。例:1111^1111=0;

3、任何数和0做异或运算,结果为任何数。例:1111^0=1111;

通过以上的三条特性,我们发现当异或两个相同的数时,答案正好为0,而0和其他数异或正好为其他数,这正好满足题目所给的条件。我们举例子说明:如数组元素为 [2,2,1,1,5],对数组元素依次进行异或运算,2^2^1^1^5=0^5=5;正好等于数组中单着的那个数,我们写出如下代码:

class Solution {
public:
    int singleNumber ( vector < int > & nums )
    {        
         //用c来记作返回结果
         int c = 0;
         //遍历数组所有元素,并且每个进行^运算
         for ( auto x : nums )
         {
                //按位异或每个元素
                c ^= x;
         }
                return c;
    }
};

?关于位运算的题目,掌握了几种方法,以后遇见就不会觉得难,而不知道这几种方法的做题确实是做不出来,所以二进制的题目还是要多进行积累。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:38:39  更:2021-08-17 15:38:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 17:01:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计