蓝桥杯 Day 01 位运算的奇淫巧计

 百度百科位运算

含义Pascal语言C语言Java
按位与a and ba & ba & b
按位或a or ba | ba | b
按位异或a xor ba ^ ba ^ b
按位取反not a~a~a
左移a shl ba << ba << b
带符号右移a shr ba >> ba >> b
无符号右移//a>>> b

 

1.& 与运算

       同为1则为1,其余为0:1&1=1 、1&0=0、0&0=0

       奇淫巧计:

        /*
		 * 该数与该数-1相与,即可消除最后一个1
		 * 例:9
		 * 1001
		 *    &
		 * 1000
		 * -----
		 * 1000
		 * */

                     【题目】判断一个整数是不是2的整数次方

                     【思路】将该数字转换为2进制之后,只有一个位上有1,用与运算消除一个1,判断是否为0,为0则表示是2的整数次方。

public class 2的整数次方 {
/*
 * 用一条语句判断一个整数是不是2的整数次方
 * */
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int N = scanner.nextInt();
		if((N&(N-1)) == 0) {
			System.out.println("是");
		}else {
			System.out.println("不是");
		}
	}

}

                        【题目】输入一个整数,输出该数二进制表示中1的个数。

                        【思路】该数与该数-1相与,即可消除最后一个1,循环消除,统计消除了几次即可求得1的个数

public class N {
/*
 * 输入一个整数,输出该数二进制表示中1的个数。
 * */
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int N =scanner.nextInt();
		System.out.println(Integer.toString(N, 2));
		int count = 0;
		while(N!=0) {
			N = N&(N-1);
			count++;
		}
		System.out.println(count);
	}

 

2.^异或运算

           具有相加不进位的特点,可用于消除两个重复的数,1^1 = 0 、1^0=1 、0^0=0

          【题目】一个数组里面除了某一个数字外,其余数字都出现了两次,请找出这个数。

          【思路】利用异或运算的特点,所有数字异或,消除重复的数字,剩下的结果就是这个落单的数。

public class 找出落单的那个数 {
/*
 * 一个数组里面除了某一个数字外,其余数字都出现了两次,请找出这个数。
 * 
 * */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = new int[]{1,1,2,2,3,3,4,4,5,5,6};
		int x = 0;
		for (int i = 0; i < arr.length; i++) {
			x = (x^arr[i]);
		}
		System.out.println(x);
	}

}

            【题目】把1-1000的数放入有1001个空间的数组中,但有一个是重复的,找出这个数

            【思路】由于异或是消除重复的,我们可以构建重复的数,将1-1000 和数组相异或,即(1^2...^n^...^1000)^(1^2^...n^n^...1000),两个的会消除,里面会出现3个n,消除之后,即可得出n

public class 唯一成对的数 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int N = 1001;
		int[] arr = new int[N];
		//给数组赋值
		for (int i = 0; i < arr.length-1; i++) {
			arr[i] = i+1;
		}
		//给末尾的未赋值的元素赋随机数
		arr[arr.length-1] = new Random().nextInt(N-1)+1;
		
		//随机的地址和末尾地址值的交换
		int index = new Random().nextInt(N);
		swap(arr, index, arr.length-1);
		
		for (int i : arr) {
			System.out.print(i+" ");
		}
		int x = 0;

		for (int i = 1; i <= N-1; i++) {
			x = (x^i);
		}
		for (int i = 0; i < arr.length; i++) {
			x = (x^arr[i]);
		}
		System.out.println("\n"+x);
	}
	
	public static void swap(int[] arr,int index,int index2) {
		//数组元素交换
		int t;
		t = arr[index];
		arr[index] = arr[index2];
		arr[index2] = t;
		
	}
	

综合题:

                   【题目】输出一个数的奇偶位互换后的数

                   【思路】

9 的奇偶位呼唤

1001

        &

1010

-------------

A:1000              可留下偶数位的数

 

1001

        &

0101

------------

B:0001              可留下奇数位的数

A向右移1位,B向左移1位,相异或,即可求出来互换后的数

0100

       ^

0010

-----------

0110

public class 交换奇偶位 {
	/*
	 * 输出一个数的奇偶位互换后的数
	 * */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int N = 9;//1001
		int a = (N&0xaaaaaaaa);//1010 1010 1010 1010...
		int b = (N&0x55555555);//0101 0101 0101 0101...
		System.out.println((a>>1)^(b<<1));
	}

}

 提高题:

             【题目】数组中只有一个数出现了1次,其余的数都出现了K次,请输出出现了1次的数。

             【思路】将所有的数转换成次数进制,每一位分别相加在一起,对次数取余,出现K次的余数为0,剩余的则是出现1次的数的K进制数,再用pow方法转成十进制,即可还原成该数。

public class 出现K次与出现1次 {
/*
 * 数组中只有一个数出现了1次,其余的数都出现了K次,请输出出现了1次的数。
 * */
	public static int k(int[] arr , int N) {
		
		int value = 0;
		int maxlen = 0;
		char[][] kradix = new char[arr.length][];
		for (int i = 0; i < arr.length; i++) {
			kradix[i] = new StringBuilder(Integer.toString(arr[i], N)).reverse().toString().toCharArray();
			if (kradix[i].length>maxlen) {
				maxlen = kradix[i].length;
			}
		}
		int[] resAry = new int[maxlen];
		//不进位加法,所有的数的同一位一块相加,大于的部分不用看,加0即可
		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < maxlen; j++) {
				if(j >= kradix[i].length)
					//该位置是0
					resAry[j]+=0;
				else 
					//求该位置不进位加法转换成整型
					resAry[j]+=(kradix[i][j] - '0');
			}
		}
		
		for (int i = 0; i < maxlen; i++) {
			/*
			 * 
			 * 将所有的数一块加,最后对N取余即可得出该位的数
			 * */
			value += (resAry[i]%N)*(int)(Math.pow(N, i));
		}
		return value;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int N = 5 , Tag=1;
		int[] arr = new int[N*5+1];//5个重复的N次的数和一个不重复的数
		for (int i = 0; i < arr.length-1; i+=N) {
			for (int j = 1; j <= N; j++) {
				arr[i+j-1] = Tag;
			}
			Tag++;
		}
		arr[arr.length-1] = Tag;
		for (int i : arr) {
			System.out.print(i+" ");
		}
		System.out.println("\n"+k(arr, N));
	}

}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值