位运算介绍:
什么是位运算呢?位运算就是二进制数据进行运算的运算符,这里我们主要说到左移,右移,按位与,按位或,按位取反,异或。
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
样例
输入:num1 = 1 , num2 = 2
输出: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,2,3,3,4,4]
输出:[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};
}
};