位运算介绍
什么是位运算呢?位运算就是二进制数据进行运算的运算符,这里我们主要说到左移,右移,按位与,按位或,按位取反,异或。
1.左移<< 1010<<1 1010左移一位后:10100 即向左移动,低位补0 2.右移>> 1010右移一位后:0101 各二进位全部右移若干位,对无符号数,高位补0,有符号数,右移补1 3.按位与& 按位与与代码中的逻辑运算从差不多,两个都是1才是1,否则是0 如:1 0 1 0 & 1 1 0 0 ———————————— 1 0 0 0 4.按位或| 按位或和我们代码中加的逻辑运算差不多,在对两个二进制数进行或运算时,只要其中一个有1,那么就是1,两个都为0才是0 如:1 0 1 0 | 0 1 1 0 _____________ 1 1 1 0 5.按位取反~ 1变0,0变1 如:~1010 取反后:0101 6.异或 相同为零,不同为1 如: 1 0 1 0 0 1 ^ 1 1 0 0 1 0 _______________ 0 1 1 0 1 1
小技巧:
去掉最后一位 x>>1 在最后一位加个0 x<<1 在最后一位加个1 (x<<1)|1 把最后一位变成1 x|1 把最后一位变成0 (x|1)-1 最后一位取反 x^1 把右数第k为变成1 x|(1<<(k-1)) 解释:将1向左移动k-1位,第k位是1,1到k-1位是0 吧右数第k位变成0 x&(~(1<<(k-1))) 解释:1向左移动k-1位,第k位是1,1到k-1位是0,取反后在与
位运算符优先级比较靠后,结合使用时一般需加上括号
写一个函数,求两个整数之和,要求在函数体内不得使用 +、-、×、÷+、-、×、÷ 四则运算符号。
数据范围
−1000≤num1,num2≤1000−1000≤num1,num2≤1000
样例
1. 输入:num1 = 1 , num2 = 2 2. 3. 输出:3
// 1100 // 1010 //10110 class Solution { public: int add(int num1, int num2) { int a,b; a=num1^num2;//将不进位的相加 b=(num1&num2)<<1;//将进位的相加 return a+b; } };
例二 将 x 的二进制表示中第 i 位和第 j 位的值互换,并输出互换后的结果
给定一个正整数 xx,请你将 xx 的二进制表示中第 ii 位和第 jj 位的值互换,并输出互换后的结果。
注意: xx 的二进制表示的最右边为第 00 位。
输入格式
共一行,包含三个整数 x,i,j
输出格式
一个整数,表示互换后的结果。
数据范围
1≤x≤2^31−11≤x≤2^31−1,
0≤i,j≤30.
输入样例1:
38 2 4
输出样例1:
50
输入样例2:
1 0 2
输出样例2:
4
分四种情况:
1. 两个位置均为1
2.两个位置均为0
3.一个位置为1,一个位置为0
4.一个位置为0,一个位置为1
1和2两种情况不需要做处理
AC代码:
#include<bits/stdc++.h> using namespace std; int main() { int m,a,b,result; cin>>m>>a>>b; result=m; int i=m>>a&1; int j=m>>b&1; if(i&&!j) result=m-(1<<a)+(1<<b);//减去原有位置上1的值加上变化后1位置的值 if(!i&&j) result=m+(1<<a)-(1<<b);//加上原有位置上1的值减去变化后1位置的值 cout<<result<<endl; return 0; }
一个整型数组里除了两个数字之外,其他的数字都出现了两次。
请写程序找出这两个只出现一次的数字。
你可以假设这两个数字一定存在。
数据范围
数组长度 [1,1000][1,1000]。
样例
1. 输入:[1,2,3,3,4,4] 2. 3. 输出:[1,2]
AC代码:
class Solution { public: vector<int> findNumsAppearOnce(vector<int>& nums) { int m=1,n,j=0,x=0,y=0; n=nums.size(); for(int i=0;i<n;i++)//先遍历异或得出x异或y的值 { j^=nums[i]; } while((j&m)==0)//找出第一个x和y不相等的二进制位 { m<<=1; } for(int i=0;i<n;i++) { if(nums[i]&m)//将含x和含y的分为两组 x^=nums[i]; else y^=nums[i]; }//最终异或出来的两数即为x和y的值 return vector<int>{x,y}; } };