更新二进制位
题目链接http://www.lintcode.com/zh-cn/problem/update-bits/
题目描述
给出两个32位的整数N和M,以及两个二进制位的位置i和j。写一个方法来使得N中的第i到j位等于M(M会是N中从第i为开始到第j位的子串)
样例
N = (10000000000)2,
M = (10101)2, i = 2, j = 6
返回N = (10001010100)2
class Solution {
public:
/**
*@param n, m: Two integer
*@param i, j: Two bit positions
*return: An integer
*/
int updateBits(int n, int m, int i, int j) {
// write your code here,位数从0开始.
unsigned int mask;
/*
如果j<31,将i到j位清0,利用((1<<(j+1))-(1<<i))得到i~j之间全是1的数,再取反;
如果j=32,i~最高位全部清0,(1<<i)-1可得到i~最高位之间全是0,其他位为0的数;
*/
if(j < 31) {
//方法1
//mask = ~((1 << (j+1)) - (1 << i));
//方法2
mask = ~((((0xFFFFFFFF) << (31 - j)) >> (31 - j + i)) << i);
}
else
mask = (1 << i) - 1;
return (m << i) + (n & mask);
}
};
A + B问题
题目链接http://www.lintcode.com/zh-cn/problem/a-b-problem/
题目描述:给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。
主要利用异或运算来完成
异或运算有一个别名叫做:不进位加法,那么a ^ b就是a和b相加之后,该进位的地方不进位的结果,然后下面考虑哪些地方要进位,自然是a和b里都是1的地方,a & b就是a和b里都是1的那些位置,a & b << 1 就是进位之后的结果。所以:a + b = (a ^ b) + (a & b << 1),令a’ = a ^ b, b’ = (a & b) << 1,可以知道,这个过程是在模拟加法的运算过程,进位不可能一直持续,所以b最终会变为0。
class Solution {
public:
/*
* @param a: The first integer
* @param b: The second integer
* @return: The sum of a and b
*/
int aplusb(int a, int b) {
// write your code here, try to do it without arithmetic operators.
while (b != 0) {
int c = a & b;
a = a ^ b;
b = c << 1;
//cout<<a<<b<<endl;
}
return a;
}
};
检验整数n是不是2的幂数
题目链接http://www.lintcode.com/zh-cn/problem/o1-check-power-of-2/
如果n是2的幂数
- n > 0
- n的二进制数中只有一个1
class Solution {
public:
/*
* @param n: An integer
* @return: True or false
*/
bool checkPowerOf2(int n) {
// write your code here,考虑特殊情况0和最小负数
return n > 0 && ((n & (n - 1)) == 0);
}
};
计算在一个 32 位的整数的二进制表式中有多少个 1
题目链接http://www.lintcode.com/zh-cn/problem/count-1-in-binary/
由x & (x - 1)消去x最后一位的1可知。不断使用 x & (x - 1) 消去x最后一位的1,计算总共消去了多少次即可。
class Solution {
public:
/**
* @param num: an integer
* @return: an integer, the number of ones in num
*/
int countOnes(int num) {
// write your code here
unsigned int n = (unsigned int)num;
int times = 0;
while(n)
{
n = n & (n - 1);
times++;
}
return times;
}
};
如果要将整数A转换为B,需要改变多少个bit位?
题目链接http://www.lintcode.com/zh-cn/problem/flip-bits/
可以转化为A^B中1的个数
class Solution {
public:
/**
*@param a, b: Two integer
*return: An integer
*/
int bitSwapRequired(int a, int b) {
// write your code here
int c = a ^ b;
int ret = 0;
while (c) {
ret += 1;
//cout<<c<<endl;
c = c & (c - 1);
}
return ret;
}
};
数组中,只有一个数出现一次,剩下都出现两次,找出出现一次的数
题目链接http://www.lintcode.com/en/problem/single-number/
利用 a ^ b ^ b = a
class Solution {
public:
/**
* @param A: Array of integers.
* return: The single number.
*/
int singleNumber(vector<int> &A) {
// write your code here
int size = A.size();
if (size == 0) {
return 0;
}
int ret = A[0];
for (int i = 1; i< size; i++)
{
ret = ret ^ A[i];
}
return ret;
}
};
数组中,只有一个数出现一次,剩下都出现三次,找出出现一次的数
题目链接http://www.lintcode.com/zh-cn/problem/single-number-ii/
class Solution {
public:
/**
* @param A : An integer array
* @return : An integer
*/
int singleNumberII(vector<int> &A) {
// write your code here
int size = A.size();
int times[32] = {0};//统计每一位中1的个数
for (int i = 0; i < size; i++) {
for (int j = 0; j < 32; j++) {
if ((A[i] & (1 << j)) > 0) {
times[j] += 1;
times[j] %= 3;//防止越界
}
}
}
int ret = 0;
for (int i = 31; i >= 0; i--) {
ret = ret << 1;
ret += times[i];
}
return ret;
}
};
数组中,只有两个数出现一次,剩下都出现两次,找出出现一次的数
题目链接http://www.lintcode.com/zh-cn/problem/single-number-iii/
求二进制中最后一位1的个数
原码,二进制表示
反码,正数的反码就是原码,负数的反码是符号位不变,其余位取反
补码,正数的补码就是原码,负数的补码是反码 + 1
在计算机中都是采用补码的形式存储
所以,a&-a就是a最后一位1的位置
不妨假设出现一个的两个元素是x,y,那么最终所有的元素异或的结果就是res = x^y。并且res!=0,那么我们可以找出res二进制表示中的某一位是1。对于原来的数组,我们可以根据这个位置是不是1就可以将数组分成两个部分。x,y在不同的两个子数组中。而且对于其他成对出现的元素,要么在x所在的那个数组,要么在y所在的那个数组。
class Solution {
public:
/**
* @param A : An integer array
* @return : Two integers
*/
vector<int> singleNumberIII(vector<int> &A) {
// write your code here
int size = A.size();
vector<int> ret = {0,0};
if (size == 0) {
return ret;
}
int diff = A[0];
for (int i = 1; i < size; i++) {
diff ^= A[i];
}
diff &= -diff;
for (int i = 0; i < size; i++) {
if ((A[i] & diff) == 0) {
ret[0] ^= A[i];
}
else {
ret[1] ^= A[i];
}
}
return ret;
}
};
%3
给一个很长的二进制字符串,计算除以3的余数
奇数位除以3余1,偶数位除以3余2,所以
- 奇数位1的个数等于偶数位1的个数,则余数为0
- 奇数位个数大于偶数位,个数相减后 %3
- 偶数位个数大于奇数位,个数相减后*2%3
int fun(char* s, int len) {
if (s == NULL)
return 0;
int odd_num = 0;
int even_num = 0;
int times = 1;
for(int i = len - 1; i>=0; i--) {
if(s[i] == '1') {
if(times & 1)
odd_num++;
else
even_num++;
}
times++;
}
if(odd_num > even_num)
return (odd_num-even_num)%3;
else
return (odd_num - even_num) * 2 % 3;
}
int main()
{
char a[] = "10010001101000101011001111000";
cout <<fun(a,sizeof(a) - 1);
}