位运算

来源:互联网 发布:数据库应用系统的构成 编辑:程序博客网 时间:2024/06/13 22:48

以下案例不做问题具体描述,详情参考《剑指Offer》题目10二进制中1的个数、题目40数组中只出现一次的数字、题目47不用加减乘除做加法。

案例一:题目10二进制中1的个数

//输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。class Solution {public:int  NumberOf11(int n){int count = 0;/* * 第一种解法:n与1做与运算,然后不断右移 */while (n){if (n & 1)count++;n = n >> 1;    //如果n是负数,右移后左边补“1”,将会陷入死循环}return count;}int  NumberOf12(int n){int count = 0;/* * 第二种解法:n与1做与运算,判断最低位是否为1; *            1左移,n与2做与运算,判断次低位是否为1 *///long long tmp = 1;unsigned int tmp = 1;int whileCount = 0;while (tmp){whileCount++;    //循环执行的次数和系统的整数二进制的位数相同if (n & tmp)count++;char nTwo[65];     //观察一下n和tmp的二进制char tmpTwo[65];_itoa(n, nTwo, 2);_itoa(tmp, tmpTwo, 2);cout << "n:" << nTwo << ", tmp:" << tmpTwo << endl;tmp = tmp << 1;  //1、100、1000、1000}cout << whileCount << endl;return count;}int  NumberOf13(int n){int count = 0;/** 第三种解法:n & n-1*/while (n)      //循环次数 = n中1的个数{++count;n = n & (n - 1);}return count;}};void main(){//函数名: itoa//功 能 : 把一整数转换为字符串//用 法 : char *itoa(int value, char *string, int radix);int number = 8;char string[25];_itoa(number, string, 2);     //_itoa_s ———— 第三个参数用于将数字转换成不同的进制(2、8、10、16)printf("Integer = %d, String = %s\n", number, string);cout << endl;//移位基础int i = 0x8000000f;  //这里的0x8000000f为int型数据的补码形式  int j = i >> 3;   //右移是算术移位,左端补齐的是符号位  int k = i << 3;   //左移是逻辑移位,右端补0  char itwo[33];_itoa(i, itwo, 2);printf("i:十进制 = %d, 二进制 = %s\n", i, itwo);char jtwo[33];_itoa(j, jtwo, 2);printf("j:十进制 = %d, 二进制 = %s\n", j, jtwo);char ktwo[33];_itoa(k, ktwo, 2);printf("k:十进制 = %d, 二进制 = %s\n", k, ktwo);printf("%d %x\n", i, i);   //-2147483633 8000000fprintf("%d %x\n", j, j);   //-268435455 f0000001printf("%d %x\n", k, k);   //30 1ecout << endl;Solution s;cout << s.NumberOf13(8) << endl;cout << s.NumberOf13(-8) << endl;}

 

案例二:题目40数组中只出现一次的数字

//一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。class Solution {public:void FindNumsAppearOnce(vector<int> data, int* num1, int *num2) {/* *知识点1:异或运算性质:(1)A^B=b^A;(2)X^0=x;(3)X^X=0 *难点1:整个数组分成两个子数组:每个数组只包含一个只出现一次的数字,其他数字都成对出现 */if (data.size() < 2){return;}int tmpOR = 0;for (int i = 0; i < data.size(); i++){tmpOR = tmpOR ^ data[i];}//所有数字异或运算,相同的数字抵消,最后的结果是num1, num2异或的结果//tmpOR肯定有一位是1,所有数据根据此位上是否是1分成两个子数组unsigned int indexOf1 = findFirstbitis1(tmpOR);//划分子数组,并进行各自进行异或运算*num1 = *num2 = 0;for (int j = 0; j < data.size(); j++){if (isBit1(data[j], indexOf1))*num1 = *num1 ^ data[j];else*num2 = *num2 ^ data[j];}}//寻找右边数第一位1unsigned int findFirstbitis1(int num){int indexOfBit = 0;while ((num & 1) == 0 )  //&& (indexOfBit < 8 * sizeof(int)){num = num >> 1;indexOfBit++;}return indexOfBit;}//判断num的indexBit位是否为1bool isBit1(int num, unsigned int indexBit){num = num >> indexBit;return (num & 1);}};

 

案例三:题目47不用加减乘除做加法

//求两个整数之和,要求在函数体内不得使用 + 、- 、*、/ 四则运算符号。class Solution {public:int Add(int num1, int num2){int sum, carry;do{sum = num1 ^ num2;           //不考虑进位,对每一位相加。(0+0、1+1=0;0+1、1+0=1 =====》 异或运算)carry = (num1 & num2) << 1;  //两个数先进行与运算,再左移一位num1 = sum;num2 = carry;} while (num2 != 0);             //运算结束条件:不再产生进位return num1;}};


 

0 0