位运算的技巧

  • 在处理整型数值时,可以直接对组成整性数值的各个位进行操作。这意味着可以使用屏蔽技术获得整数中的各个位
  • &(与)、|(或)、^(异或)、~(非/取反)
  • >>和>>运算符将二进制位进行右移或者左移操作
  • >>>运算符将用0填充高位;>>运算符用符号位填充高位,没有<<<运算符
  • 对于int型,1<<35与1>>3时相同的,而做百年的操作数是long型时需对右侧操作数模64
  • 与:都为1结果为1;或:有一个为1结果为1;异或:二者不同时结果为1

使用技巧:

  1. 判断奇偶数(和1做与运算结果为1是奇数,结果为0是偶数)
  2. 获取二进制位是1还是0(和1做与运算,结果再移动到最低位进行判断)
  3. 交换两个整数变量的值(三次异或运算)
  4. 不用判断语句,求整数的绝对值
异或:可以理解为不进位加法

对于任何数x,都有x^x=0,x^0=x
同自己求异或为0,同0求异或为自己

题:找出唯一成对的数

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

分析:

如果可以用辅助空间的话是很简单的,开辟一个同样大的数组,遍历原数组,将原数组对应的数字在新数组中进行统计次数即可。
但这里不允许用辅助空间,解决办法可以采取异或。

package test2019;

import java.util.Random;

public class Main {
	public static void swap(int[] a,int i,int j) {
		int t=a[i];
		a[i]=a[j];
		a[j]=t;
	}
	public static void main(String[] args) {
		int N=11;
		int[] a = new int[N];
		//将前N-1个数放在数组中,无重复
		for(int i=0;i<a.length-1;i++) {
			a[i]=i+1;
		}
		//将重复的那个数字以随机数的方式放在数组最后
		a[N-1]=new Random().nextInt(N-1)+1;//产生1-N-1之间的数,但不包含N-1
		//产生一个随机下标,将数组最后那个重复的数字随机放入数组
		int index = new Random().nextInt(N);
		swap(a, index,a.length-1);
		for(int i=0;i<a.length;i++) {
			System.out.print(a[i]+" ");
		}
		System.out.println();
		//0与1-N全部异或,得到的结果是1-N之间的异或
		int x1=0;
		for(int i=1;i<N;i++) {
			x1=x1^i;
		}
		//将1-N之间的异或与数组里的数逐个异或起来,任何两个相同的数异或为0,则多出的重复的数即赋给x1
		for(int i=0;i<a.length;i++) {
			x1=x1^a[i];
		}
		System.out.println(x1);
	}
	
}

重点在于:
  • 0与1-N全部异或,得到的结果是1-N全部异或的结果(0与任何数异或都是数本身)
  • 将1-N之间的异或与数组里的数逐个异或起来,任何两个相同的数异或为0,则多出的重复的数落单,很容易被揪出。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值