位运算的相关题目

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

请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。

例如:9的二进制表示为1001,有2位是1。

题目分析:

首先题目给我们的是一个整数,一个一般的整数大多是32位,其次在这里我们需要用之前的<< 和>>运算符对整数的二进制的每一位求与运算,从与运算的结果中,知道整数中1的个数。

方法一代码如下:

#include <stdio.h>
int main()
{
	 int i,j,k=0;
	 scanf("%d",&j); 
	 for(i=0;i<32;i++)
	 {
	 	if((j&(1<<i))==(1<<i))//前面的与运算的结果是1,刚好等于1移动到对应位置的值 
	 	k=k+1;
	 }
	 printf("%d",k);
	 
	getch();
	return 0;
 } 

运行效果:

方法二代码如下:

方法二的原理和一差不多,不同之处在于,方法二是移动了数字就不是1;

#include <stdio.h>
int main()
{
	 int i,j,k=0;
	 scanf("%d",&j); 
	 for(i=0;i<32;i++)
	 {
	 	if(((j>>i)&1)==1)//前面的与运算的结果是1,刚好等于1
	 	k=k+1;
	 }
	 printf("%d",k);
	 
	getch();
	return 0;
 } 

运行效果:

 方法三代码如下:

方法三的解题原理如下通过每一次的减1得到的结果再和上一次的数做与运算,就能消去原本的数最后的一个1,重复直到最后最开始的数为0,这时减去1的次数就是原来的数字的二进制有多少个1。

#include <stdio.h>
int main()
{
	 int count=0,j;
	 scanf("%d",&j); 
	 while(j!=0)
	 {
	 	j=j&(j-1);
	 	count++;
	 }
	 printf("%d",count);
	 
	getch();
	return 0;
 } 

运行效果:

 题目二:将整数的奇偶位互换

题目分析:如果之前没有习惯位运算,在这里有一种做法就是将输入的数变成二进制,然后用字符串数组将二进制数存在里面,然后对下标为i=2k(k属于自然数)的元素取出来放,在一个新数组的奇数位;将下标为i=2k+1(k属于自然数)的元素取出来,放在新数组的偶数位。

现在我们用为运算来解决,我们可以用0xaaaaaaaa(16进制表示1010 1010 ......)与原数做与运算,取出原数的偶数位上的数字,然后可以用0x55555555(16进制表示0101 0101......)与原数做与运算,取出原数的奇数位上的数字,然后分别将取出的数右移和左移一位,再进行异或运算,得到的结果就是我们想要的结果。

代码如下:

#include <stdio.h>
int main()
{
	int number,o,j;
	scanf("%d",&number);
	o=number&0xaaaaaaaa;
	j=number&0x55555555;
	printf("%d",(o>>1)^(j<<1)); 
	getch();
	return 0;
 } 

运行结果:

  题目三:出现k次与出现1次

数组中只有一个数出现了1次,其他的数都出现了k次,请输出只出现了1次的数。

题目分析:这道题其实可以直接用暴力解法,把每一个数出现的次数记录下来,然后选出次数为1的数字,但是在这里我们采用位运算相关的知识来进行讲解。首先这里要给大家补充一个知识点:k个相同的k进制数做不进位加法,结果为0,这句话是解题的核心。当我们将题目数组中数字全部转化为他们对应出现k次数的进制,然后进行不进位相加,这个时候数组中出现了k次的相同数字得到的结果将会是0,剩下的数字就是只出现了一次的数字,然后我们再用进制转换,将其转换为10进制,这样出现一次的数字就出来了。

示例代码如下:

#include<stdio.h>
#include<math.h>
int main(){
	int k=3; 
	int b[32] = {0};
	int i,j;
    int a[10]={11,11,11,22,22,22,33,33,33,44};
	for(i=0;i<10;i++){
		int j = 0;
		while(a[i]!=0){
			b[j]=b[j]+a[i]%k;
			b[j]=b[j]%k; 
			a[i]=a[i]/k;
			j++;
		}
	}
	int m=0;
	for(i=0;i<32;i++){
		m=m+b[i]*pow(k,i);
	}
	printf("%d",m);
	return 0;
}

 

运行效果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值