位运算的一些技巧

一、基本知识(针对二进制)

1.&:全一则一

2.|:有一则一

3.^:在二进制中,相异为一,相同为0(可理解为不进位加法:1^1=0  1^0=1)

         概括起来就是:符合交换律、结合律、相反性(x^x=0,x^0=x,x^y^y=x【可去重】)

4.~:非运算/取反

5.>>、<<:(带符号)右移、左移,符号后面的表示移动的位数(对于int型(32位),1<<35和1<<3一样的,其中35%32=3,对于long型,需对右侧操作数%64)【为正补0,为负补1】

6.有>>>而无<<<:最高位补0

二、应用:

1.判断奇偶:x&1=1为奇数,x&1=0为偶数

2.获取二进制位是1还是0:1&1=1,1&0=0,0&1=1,0&0=0

3.交换两个整数变量的值:

int temp = a^b;

a = a^temp;

b = b^temp; 

4.不用判断语句,求整数的绝对值:

首先要知道求负数:~x+1= -x

例如:-7的绝对值7是111,即0000 0000 0000 0000 0000 0000 0000 0111,取反码转换为1111 1111 1111 1111 1111 1111 1111 1000,然后  +1——》1111 1111 1111 1111 1111 1111 1111 1001

因为>>/<<是带符号的位运算,正数移动后补0,符数移动后补1

求绝对值:

int i = a>>31;//第32位是符号位,0为正数,1是负数,找正负

return ((a^i)-i);//任何数x^0=本身(说明正数)

 

参考:https://www.cnblogs.com/dyllove98/archive/2013/08/04/3236802.html
题目:1~1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

import java.util.Arrays;
import java.util.Random;

public class blue01 {

	public static void main(String[] args) {
		int N = 1001;
		int all = 0, sum = 0;
		int[] arr = new int[N];
		for (int i = 0; i < arr.length - 1; i++) {
			arr[i] = i + 1;
			all += arr[i];
		}
		arr[arr.length - 1] = new Random().nextInt(N - 1) + 1;
		all += arr[arr.length - 1];
		System.out.println(all);
		System.out.println(Arrays.toString(arr));

		for (int i = 1; i < arr.length; i++) {
			sum += i;// 0+1+2+3...+1000
		}
		System.out.println(sum);
		int x = all - sum;
		System.out.println(x);
		// 上面用的是不借助辅助空间,以下是借助辅助空间
		System.out.println("***********");
		int[] helper = new int[N];
		for (int i = 0; i < N; i++) {
			helper[arr[i]]++;// 开辟一个数组来存储元素出现的次数
			if (helper[arr[i]] == 2) {// 由题可知,次数大于2的即为重复的数 System.out.println(arr[i]);
			}
		}

		System.out.println(Arrays.toString(helper));
	}
}

 

 

还可以采用等差数列的方法

import java.util.Arrays;
import java.util.Random;

public class blue01 {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int N = 1001;
		int all = 0, sum = 0;
		;
		int[] arr = new int[N];
		for (int i = 0; i < arr.length - 1; i++) {
			arr[i] = i + 1;
			all += arr[i];
		}
		arr[arr.length - 1] = new Random().nextInt(N - 1) + 1;
		all += arr[arr.length - 1];
		System.out.println(all);
		System.out.println(Arrays.toString(arr));

		for (int i = 1; i < arr.length; i++) {
			sum += i;// 0+1+2+3...+1000
		}
		System.out.println(sum);
		int x = all - sum;//减法运算得到的数为重复的数
		System.out.println(x);
}
}

补题:

整数转换。编写一个函数,确定需要改变几个位才能将整数A转成整数B。

 示例1:

 输入:A = 29 (或者0b11101), B = 15(或者0b01111)
 输出:2


 示例2:

 输入:A = 1,B = 2
 输出:2

画图更理解一些

public class ConvertIntegerIcci0506 {
	public static void main(String[] args) {
		System.out.println(convertInteger(29, 15));
	}

	static public int convertInteger(int A, int B) {
		int temp = A ^ B;
		System.out.println(temp);
		int count = 0;
		while (temp != 0) {
			temp &= (temp - 1);// 去掉二进制表示的最右边的1
			count++;
		}
		return count;
	}
}

 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值