CarceerCup 系列 第五章 Bit Manipulation

题目翻译和代码有不正确的地方欢迎批评指正.有好的方法欢迎交流。

第一题:

You are given two 32-bit numbers, N and M, and two bit positions, i and j. Write a method to set all bits between i and j in N equal to M (e.g., M becomes a substring of N located at i and starting at j).
EXAMPLE:
Input: N = 10000000000, M = 10101, i = 2, j = 6
Output: N = 10001010100

把N从左边数的第i到j位设置成M的值

代码如下:

#include<stdio.h>

int main()
{
	int N, M;
	int i, j;
	int x = 0;
	scanf("%d %d", &N, &M);
	scanf("%d %d", &i, &j);
	x = (0|M)<<i; //000M00
	N &= (((~0) << (j-i+1)) <<i) | (~((~0)<<i)); //N000N
	N |= x;
	printf("%d %d", N, M);
}



第二题:

Given a (decimal - e.g. 3.72) number that is passed in as a string, print the binary representation. If the number can not be represented accurately in binary, print “ERROR”

还不知道怎么写代码。

第三题:

Given an integer, print the next smallest and next largest number that have the same number of 1 bits in their binary representation.

给你一个整数n,求出最小的比n大并且和n的二进制中1的个数一样多的数。找出最大的比n小并且和n含的1一样多的数。

方法一:

从n开始依次递增,递减,找到满足条件的数。

方法二:

寻找大数:

1.从n的二进制数的右边往左寻找到第一位是1,并且该位左边的一位是0

2.把找到的这一位变为0,左边的变为1;

3.把变为0的那一位右边的1全部移到最右边(最低位)

寻找小数原理相似。

代码如下:

#include<stdio.h>
int Findlarge(int);
int Findsmall(int);
int main()
{
	int n;
	int small = 0, large = 0;
	scanf("%d", &n);
	assert(n >1)
	large = Findlarge(n);
	small = Findsmall(n);
	printf("%d %d", large, small);
}

int Findlarge(int n)
{
	int k, count;
	k = 1;
	count = 0;
	while((n & k) == 0)//跳过开始的0
	{
		k<<= 1;
	}
	while((n&k)!= 0)//寻找位的值为1,但是右边的位为0 的位
	{
		k<<= 1;
		count++;
	}
	n |= k;//
	k >>= 1;
	n&= ~k;
	count--; //右边1的个数,
    while(k > 0)
	{
		if((n &k)!= 0)
			n &= ~k;
		k >>= 1;
	}
	n |= ~((~0)<<count);
	return n;
}

int Findsmall(int n)
{
	int k, count;
	k = 1;
	count = 0;
	while((n&k) != 0)
	{
		k<<= 1;
		count++;
	}
	while((n&k) == 0)
	{
		k<<= 1;
	}
	n &= ~k;
	k >>= 1;
	n |= k;
	while(k > 0)
	{
		k >>= 1;
		if(count > 0)
			n |= k;
		else
		{
			n &= ~k;
		}
		count--;
	}
	return n;
}


第四题:

Explain what the following code does: ((n & (n-1)) == 0).

用来判断n的二进制中是不是只含有一个1,

第五题:

Write a function to determine the number of bits required to convert integer A to integer B.
Input: 31, 14
Output: 2

其实也就是判断两个数,有多少位不同。

用上一题的结论。

代码如下:

#include<stdio.h>

int main()
{
	int n, m;
	int count;
	scanf("%d %d", &n, &m);
	m ^= n;
	count = 0;
	while(m)
	{
		count++;
		m &= m-1;
	}
	printf("%d\n", count);
}


第六题:

Write a program to swap odd and even bits in an integer with as few instructions as possible (e.g., bit 0 and bit 1 are swapped, bit 2 and bit 3 are swapped, etc).

交换一个数字的奇数位和偶数位.

代码如下:

#include<stdio.h>
int main()
{ 
	int x;
	scanf("%d", &x);
	x = ((x& 0xaaaaaaaa)>>1) | ((x&0x55555555)<<1);
	printf("%d", x);
}


第七题:

An array A[1... n] contains all the integers from 0 to n except for one number which is missing. In this problem, we cannot access an entire integer in A with a single operation. The elements of A are represented in binary, and the only operation we can use to access them is “fetch the jth bit of A[i]”, which takes constant time. Write code to find the missing integer. Can you do it in O(n) time?

题意如下:

给你一个数组A[n],里面存储了0到n的n个数字,你不能获得数组的数字,只能知道数组中数字的第k位是1还是0,你能在o(N)的时间里找到不在数组中的那个数字吗?

思路如下:

先求出n的有效位数,假如为k位,创建一个一个大小为2^k+1次方大小的数组,复制A[n]中的元素到这个数组中,后面的元素从n依次加1;

然后统计每个位上面1和0的个数,就可以知道要找的数字的每一位是0还是1.

假如n=4,扩充到7,使每一位上面的0和1的个数想同。

0000

0001

0010

0011

0100

0101

0110

0111

代码如下:

#include<stdio.h>
#include<malloc.h>
#include<assert.h>

void Find(int* ,int , int , int *);
int GetBitof1(int *, int , int);//获得第k位0或者1的个数
int main()
{
	int *A, n;
	int i;
	int result = 0;
	int m = 1;
	int count = 0;
	int temp;
	scanf("%d", &n);
	assert(n > 0);
	temp = n;
	while(temp)//统计n的有效位
	{
		temp >>= 1;
		count++;
	}
	//count++;
	m <<= count;
	A = (int *)malloc(sizeof(int) * (m-1));
	assert(A != NULL);
	printf("Input the value form 0~n\n");
	for(i = 0;i < n; ++i)
		scanf("%d", A+i);
	for(; i < m-1; ++i)//扩充数组,使第k位上面1和0的个数相同
		A[i] = i+1;

	for(i = 0; i < m-1; ++i)//观察结果
		printf("%d ", A[i]);
	printf("\n");

	Find(A, m-1, 1, &result);
	printf("%d ", result);
	free(A);
	return 0;
}

void Find(int *A, int n, int k, int *result)
{
	int m = 1;
	int count1 = 0;
	int count0 = 0;
	m <<= k-1;
	if(m > n)
		return;
	count1 = GetBitof1(A, n, k);
	count0 = n-count1;
	if(count0 > count1)//0比1多,说明这一位应该是1
	{
		*result |= m;
	//	Find(A, n, k+1, result);
	}
	Find(A, n, k+1, result);
}

int GetBitof1(int *A, int n, int k)
{
	int count = 0;
	int i;
	int value = 1;
	value <<= k-1;
	for(i = 0; i < n; ++i)
	{
		if(A[i] &value)
			count++;
	}
	return count;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值