博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
位运算
阅读量:5091 次
发布时间:2019-06-13

本文共 2254 字,大约阅读时间需要 7 分钟。

  1. 输入一个整数,输出该数二进制表示中1的个数。附加题:判断一个数是否是2的幂。
  2. 一个整数数组里除了两个数字以外,其他数字都出现两次。请找出只出现一次的数字,要求时间复杂度O(n),空间复杂度O(1)。
  3. 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/即加减乘除四则运算符号。

1、思路:

  常规方法:逐位和1做与运算,看是否为1。如果右移位,当符号位为1时,会陷入死循环(高位补1)。所以选择左移位,当标志位为0时说明所有位都移动完成。

  巧妙方法:当n-1时,与n相比,最右边的1变为0,再右侧的0变为1。所以n&(n-1)不为0,则计数加1,有几个1就有几次循环。

  判断2的幂:用二进制表示该数,如果是2的幂,则只有高位出现1,其他位都是0。

1 int NumberOf1_Solution1(int n) 2 { 3     int count = 0; 4     unsigned int flag = 1; 5     while(flag) 6     { 7         if(n & flag) 8             count ++; 9  10         flag = flag << 1;11     }12  13     return count;14 }15 16 int NumberOf1_Solution2(int n)17 {18     int count = 0;19  20     while (n)21     {22         ++ count;23         n = (n - 1) & n;24     }25  26     return count;27 }

 

2、思路:

  空间复杂度O(1)说明不能用hash。真经:异或自己得0,异或0得自己。首先,所有数组中的数字都异或一遍,出现两次的相互抵消,最后的结果是两个只出现1次的数字异或的结果。其次,最右边出现1的位说明两个数在该位上不同,则以该位为0或为1分隔成两个数组。最后,在新的两个数组上都异或一遍,得两个数字。

1 void FindNumsAppearOnce(int data[], int length, int* num1, int* num2) 2 { 3     if (data == NULL || length < 2) 4         return; 5    6     int resultExclusiveOR = 0; 7     for (int i = 0; i < length; ++ i) 8         resultExclusiveOR ^= data[i]; 9   10     unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);    11   12     *num1 = *num2 = 0;13     for (int j = 0; j < length; ++ j)14     {15         if(IsBit1(data[j], indexOf1))16             *num1 ^= data[j];17         else18             *num2 ^= data[j];19     }20 }21   22 // 找到num从右边数起第一个是1的位23 unsigned int FindFirstBitIs1(int num)24 {25     int indexBit = 0;26     while (((num & 1) == 0) && (indexBit < 8 * sizeof(int)))27     {28         num = num >> 1;29         ++ indexBit;30     }31   32     return indexBit;33 }34  35 // 判断数字num的第indexBit位是不是136 bool IsBit1(int num, unsigned int indexBit)37 {38     num = num >> indexBit;39     return (num & 1);40 }

 

3、思路:

  只能用位运算。模拟加法过程,先各个位上相加不考虑进位,再考虑进位,最后把进位加上。而0+0=0,1+1=0,0+1=1,1+0=1,即异或的结果。只有1+1=0才会产生进位,那么1&1=1,将1左移表示进位。

1 int Add(int num1, int num2) 2 { 3     int sum, carry; 4     do 5     { 6         sum = num1 ^ num2; 7         carry = (num1 & num2) << 1; 8   9         num1 = sum;10         num2 = carry;11     }12     while(num2 != 0);13  14     return num1;15 }

 

 

 

转载于:https://www.cnblogs.com/wangpengjie/archive/2013/03/27/2984261.html

你可能感兴趣的文章
Mysql与Oracle 的对比
查看>>
jquery实现限制textarea输入字数
查看>>
Codeforces 719B Anatoly and Cockroaches
查看>>
jenkins常用插件汇总
查看>>
c# 泛型+反射
查看>>
第九章 前后查找
查看>>
Python学习资料
查看>>
jQuery 自定义函数
查看>>
jquery datagrid 后台获取datatable处理成正确的json字符串
查看>>
ActiveMQ与spring整合
查看>>
web服务器
查看>>
第一阶段冲刺06
查看>>
EOS生产区块:解析插件producer_plugin
查看>>
JS取得绝对路径
查看>>
排球积分程序(三)——模型类的设计
查看>>
HDU 4635 Strongly connected
查看>>
格式化输出数字和时间
查看>>
页面中公用的全选按钮,单选按钮组件的编写
查看>>
java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
查看>>
(旧笔记搬家)struts.xml中单独页面跳转的配置
查看>>