算法基础——位运算

1、找出数组中唯一成对的那个数

	1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现
	一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空
	间,能否设计一个算法实现?

思路1:按位异或再异或得到重复的那个数

		int n=11;
		int[] arr = new int[n];
		int index = new Random().nextInt(n);
		arr[arr.length-1]=new Random().nextInt(n-1)+1;
		
		for(int i=0; i<arr.length-1; i++) {
			arr[i]=i+1;
			
		}
		int num=0;
		for(int i=1; i<n; i++) {
			num = (num ^ i);
		}
		for(int i=0; i<n; i++) {		
			num = num ^ arr[i];
		}
		for(int i=0; i<n; i++) {	
			System.out.print(arr[i]+",");

		}
		System.out.println("\n"+num);

思路2:暴力求解,利用数组存储

//开辟一个存储空间将数值作为下标进行遍历
		int[] helper = new int[n];
		for(int i=0; i<n; i++) {
			helper[arr[i]]++;
		}
		for(int i=0; i<n; i++) {
			if(helper[i]==2) {
				System.out.println(i);
				break;
			}
		}

2、二进制中1的个数

请实现一个函数,输入一个整数,输出该数二进制表示中1 的个数
例:9的二进制表示为1001,1的个数为2
思路1:整数32位,左移和1进行‘与’运算
思路2:数减一,使低位上1变为0,其后变为1,之后再与原数做‘与’运算,使后面的1变为0,count++,直到数值变为0

Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		//Integer.toString(int par1,int par2)
		//par1表示要转成字符串的数字,par2表示要转成的进制表示
		System.out.println(Integer.toString(n,2));
		int count = 0;
		//1向左移动
		for(int i=0; i<32; i++){
			if((n&(1<<i)) == (1<<i)) {
				count++;
			}
		}
		//数字向右移动
		for(int i=0; i<32; i++){
			if(((n>>i)&1) == 1) {
				count++;
			}
		}
		System.out.println(count);
public static void method2(int n) {
		int count = 0;
		while(n!=0) {
			n = (n&(n-1));
			count++;
		}
		System.out.println("method2:"+count);

	}

3、2的整数次方

用一条语句判断一个整数是不是2的整数次方
思路:该整数的二进制表示中只有一个‘1’,利用题2思路,减一应为0

		if(((n-1)&n) == 0) {
			System.out.println("yes");
		}
		else {
			System.out.println("no");
		}

4、将整数的奇偶位互换

public static void main(String[] args) {
		int a = 6;
		int b = m(a);
		System.out.println(Integer.toString(a, 2));
		System.out.println(Integer.toString(b, 2));
		System.out.println(b);
	}
	public static int m(int i) {
		//0x为16进制,8个a为8个1010即int的32位
		//和1010 1010 1010 。。。。。做与运算取出偶数位
		int ou = i&0xaaaaaaaa;
		//和0101 0101 0101 。。。。。做与运算取出奇数位
		int ji = i&0x55555555;
		return (ou>>1)^(ji<<1);//异或连起来
	}

0110
1001
9

5、0~1间浮点实数的二进制表示

题:给定一个介于0和1之间的实数,类型为double,打印它的二进制表示,若该数字无法精确地用32位以内的二进制表示,则打印“ERROR”
思路:乘2,判断整数位,消除整数位,直至减为0

public static void main(String[] args) {

		double num = 0.625;
		StringBuilder sb = new StringBuilder("0.");
		
		while(num>0) {
			double x = num*2;
			if(x>=1) {
				sb.append("1");
				num = x-1;
			}
			else {
				sb.append("0");
				num = x;
			}
			if(sb.length() > 34) {
				System.out.println("ERROR");
				return;
			}
		}
		System.out.println(sb);
		System.out.println(sb.toString());
	}

6、出现k次与出现1次

题:数组中只有一个数出现1次,其他数都出现了k次,请输出只出现了1次的数
思路:2个二进制数做不进位加法,结果为0,
k个k进制数做不进位加法,结果为0,
将数组中的数转换为k进制,进行不进位加法,结果保留的数再转换为10进制

public static void main(String[] args) {
		int[] arr= {1, 1, 1, 3, 3, 3, 5, 6, 6, 6};
		int len = arr.length;
		char[][] kRadix = new char[len][];
		
		int k=3;
		int maxLen = 0;
		//对每个数字,求每个数字的三进制字符串并翻转,数组的开头是低位,然后转为字符数组
		for(int i=0; i<len; i++) {
			kRadix[i] = new StringBuilder(Integer.toString(arr[i], k)).reverse().toString().toCharArray();
			if(kRadix[i].length > maxLen) 
				maxLen = kRadix[i].length;
		}
		//每一列的和
		int[] newArr = new int[maxLen];
		//不进位加法,计算出每一列的和存储到newArr中
		for(int i=0; i<len; i++) {
			for(int j=0; j<maxLen; j++) {
				if(j >= kRadix[i].length)
					newArr[j]+=0;
				else
					newArr[j] += (kRadix[i][j] - '0'); //char转化为数字,即与‘0’的差距
			}
		}
		int num=0;
		//每一列取余,再转换为10进制数
		for(int i=0; i<maxLen; i++) {
			num += (newArr[i] % k) * (int)(Math.pow(k, i));
		}
		System.out.println(num);
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值