现在的位置: 首页 > 综合 > 正文

位操作面试题集锦

2013年09月02日 ⁄ 综合 ⁄ 共 2923字 ⁄ 字号 评论关闭

位操作面试题集锦

都是从网上找的,自己按照参考答案写了一遍,这里汇总一下,留着复习。也希望路过的挑刺指正。

左移位:将运算数的二进制码整体(包括符号位)左移指定位数,左移之后的空位用0补充
右移位:将运算数的二进制码整体右移指定位数,右移之后的空位用符号位补充(正数用0补充,负数用1补充)

 

1 写一个BitUtil类,设置0、1经常用到。

public class BitUtil{
	public static int setBit(int num,int index,boolean b){
		if(b) return (num | (1<<index));
		int mask = ~(1<<index);		//~ 是按位取反
		return (num & mask);
	}
	public static boolean getBit(int num,int index){
		int mask = num & (1<<index);
		return (mask != 0);		
	}
}

2 统计一个整数二进制式‘1’的个数

public static void count1(int n){
		int num=n;
		int count=0;
		//解法1:每次右移,和1<<31 & 运算,不为0,则该位是1
		/**while(num!=0){
			if((num&(1<<31))!=0) count++;
			num=(num<<1);
		}**/
		//解法2: n&(n-1)的效果:n的二进制位从右往左第一个1变成0,该位置右侧全部变成1
		//						110100 & 110011 = 110000,这样每次消掉一个1
		//	-2147483648-1=2147483647 即0x80000000-1=0x7fffffff 二者相&为0
		while(num!=0){
			num&=(num-1);
			System.out.println(num);
			count++;
		}		
		System.out.println(n+"有"+count+"个1");
	}

3 实现方法将一个整数中的偶数位和奇数位交换。(是交换二进制位)   例如:将0位和1位交换,2位和3位交换 

public static void swapOddEven(int num){		
		//注释的语句方法对于负数不适用,因为负数右移时,用1填充 例如10****,
		//本来应该变成01****为正数,但是由于用了1填充, | 运算后必然还是负的
		//所以应该先右移,然后用0把填充的1替换掉
		//int result = ((0xaaaaaaaa & num)>>1)|((0x55555555 & num)<<1);		
		int result = ((num>>1)&0x55555555)|((0x55555555 & num)<<1);		
		System.out.println(result);
	}

4给定一个32bit的数值,如果输出比特位反转后的值,   如对于4bit的二进制值1011,翻转后为1101。(第1位放32位,第1位放第32位……,第32位放第一位)
  要求复杂度O(lgn),n 为比特位数。

public static void reversBits(int num){		
	/**土办法,达不到时间要求		
		for(int i=0;i<32;i++){
			int result=0;
			result=((result<<1)|(num&1));
			num=num>>1;	
		}
	**/	
		/**采用交换的方法,先两位对调,然后4位…… **/	
		num = ((num>>1)&0x55555555)|((num&0x55555555)<<1);
		num = ((num>>2)&0x33333333)|((num&0x33333333)<<2);
		num = ((num>>4)&0x0f0f0f0f)|((num&0x0f0f0f0f)<<4);
		num = ((num>>8)&0x00ff00ff)|((num&0x00ff00ff)<<8);
		num = ((num>>16)&0x0000ffff)|((num&0x0000ffff)<<16);
		System.out.println("result"+num);		
	}

5 实现函数计算将整数从A变成B需要变动几位   例如 输入:31,14 输出 2

public static void changeA2B(int a,int b){
			int count=0;
			/**
			for(int i=0;i<32;i++){
				if(BitUtil.getBit(a,i)!=BitUtil.getBit(b,i)) count++;
			}
			**/
			//或者使用Xor			
			for(int c=(a^b);c>0;c=(c>>1)){			// c=(c>>1)有没有简写方式?
				count+=(c&1);
			}			
			System.out.println("需要改动"+count+"次");
	}

6  一个数组A[1,n]能容纳n个数字,现将0到n这n+1个数字,随机的放入到数组中。    最后会有一个数字没有进入数组。现在让你找出这个数字。   但是有如下的限制,不能直接访问数组的整个元素,只能访问“A[i]的第j位”。   写出代码找出该元素。能否将时间复杂度控制在O(n)。

	/**	解法1: 借鉴编程珠玑 时间复杂度 n+n/31+31 = O(n) 		 
		解法2: 讲0~n按照二进制码表示,则最低位是0,1,0,1……,如果n奇数count(0)>count(1),n是偶数count(0)=count(1)
				所以如果确实的数为K:
					若K的最低位是0 当n为奇数时count(0)=count(1)
						    当n为偶数时count(0)=count(1)-1
					若K的最低位是1 当n为奇数时count(0)=count(1)-2
						    当n为偶数时count(0)=count(1)-1
				这样每次可以删除一半的数,时间复杂度O(n)+O(n/2)+O(n/4)+…… 但是每次都需要讲末尾为0、1的数再存储
				所以感觉效率不是很好
	**/
	public static void findTheMissOne(int [] array){
		int miss=0;
		int n = array.length;
		int memArray [] = new int[(n+30)/31];
		System.out.println(memArray.length);
		for(int i=0;i<n;i++){
			int curr = 	array[i];
			memArray[curr/31] = BitUtil.setBit(memArray[curr/31],curr%31,true); //这样调用setBit总感觉很别扭
		}
		int j=0;
		for(;j<memArray.length;j++){		
			if( (memArray[j] | (1<<31)) != -1) break;
		}
		int k=0;
		for(;k<31;k++){
			if(!BitUtil.getBit(memArray[j],k)) break;
		}
		miss = j*31+k;
		System.out.println("the missing num is :"+miss);	
	}	

参考网址:

http://blog.csdn.net/coder_xia/article/details/7922077

http://blog.csdn.net/ccccdddxxx/article/details/8002983

抱歉!评论已关闭.