二进制位运算1

_01_唯一成对的数

**问题描述

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

题解分析

我们知道,在位运算中,a^a = 0,b^0 = b。这样我们可以利用这个性质将不重复的数都消掉,就可以得到重复的那个数了。
但是1—1000中只有一个数是重复的,如果我们直接将这1001个数进行异或,就会将这个重复的数给消去。
仔细想一想,我们可以这样:我们可以用1—1000这1000个数异或后的值跟数组中的1001个元素异或,就可以得到重复的那个数了。
为什么呢?我们假设重复的数是K,那么(123KK9991000)(1239989991000)= K,
因为在等式左边的所有参与异或运算的这2001个数中,除了K这个数有3个外,其他数都有且只有2个,
又两个相同的数进行异或的结果是0,这样一来等式左边算到最后的结果就是0^K,也就是K了。
**

public class _01_唯一成对的数 {
	public static void main(String[] args) {
		int num = 11;
		int arr[] = new int[num];
		for(int i = 0;i<arr.length-1;i++) {
			arr[i]=i+1;
		}
		for(int i =0;i<arr.length;i++) {
			System.out.print(arr[i]+" ");
		}
		System.out.println();
		
		arr[arr.length-1] = new Random().nextInt(num-1)+1;//给最后一个数随机赋值
		int index = new Random().nextInt(num);//随机下标
		
		int temp = arr[arr.length-1];
		arr[arr.length-1] = arr[index];
		arr[index] = temp;
		
		for(int i =0;i<arr.length;i++) {
			System.out.print(arr[i]+" ");
		}
		int count = 0;
		for(int i = 1;i<num;i++) {
			count^=i;
		}
		for(int i = 0;i<num;i++) {
			count^=arr[i];
		}
		System.out.println();
		System.out.println(count);
		
	}
}

_02_找出落单的那个数

**题目描述:
  一个数组除了一个数字之外其他数字都只出现了两次,请写程序找出这个出现一次的数字

解题思路:
  利用位运算的异或性质:A ^ A=0 ,A ^ 0=A ,
所以我们只需对数组每一个元素都连续进行异或操作即可得出那个落单的数,成对的都被消掉了,而未成对的那一个数会被保留下来。
**

public class _02_找出落单的那个数 {
	public static void main(String[] args) {
		int arr[] = {1,2,3,4,5,1,2,3,4};
		int count = 0;
		for(int i = 0;i<arr.length;i++) {
			count^=arr[i];
		}
		System.out.println(count);
	}
}

_03_二进制中1的个数

**输入一个整数,输出该数二进制数中1的个数
*
解法分析:
方法一:

方法三:
(x-1) & x : 将x的二进制数中的低位1消去**
public class _03_二进制中1的个数 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int num = scanner.nextInt();
		System.out.println(Integer.toString(num,2));//将十进制数转化成二进制
		int count = 0;
		for(int i = 0;i<32;i++) {
			if((num&(1<<i))==(1<<i)) {
				/*
				 		1
				 <<0	1
				 num&	1100&1
				 <<1	10
				 num&	1100&10		!= 10
				 <<2	100
				 num&	1100&100  	== 100	
				 <<3	1000
				 num&	1100&1000	== 10000
				 */
				count++;
			}
		}
		System.out.println(count);
//		String biNum = Integer.toBinaryString(num);//将十进制数转化成二进制
//		System.out.println(biNum);
//		System.out.println(Integer.bitCount(num));//可以直接把二进制中的1的个数求出来
//		int count =0;
//		/*
//			10010
//		-1	10001
//		&	10000
//		-1	01111
//		&	00000
//		 */
//		while(num!=0) {
//			num = num&(num-1);
//			count++;
//		}
//		System.out.println(count);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值