位运算的奇巧淫技

一. 唯一成对的数:1-100然后随机生成一个1-100之间的数,使一个数成对(法1:异或。法2:构造辅助数列)

import java.util.Random;

public class Arraychengdui {
 
    public static void main(String[] args) {
         
        int N = 101;
        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 = 0; i < arr.length; i++) {
            System.out.print(arr[i]+ "  ");
        }
        System.out.println();
        int x1=0;
        for(int i=1;i <= N -1;i++){
            x1 = (x1^i);   // 求得1到N-1这些连续的数的异或
        }
        for(int i=0;i < N ;i++){
            x1 = (x1^arr[i]);  // 再与原来的数组arr异或,这样重复的数就有三个,不重复的数有两个,异或消除重复后,剩下的就是重复的数了
        }
        System.out.println(x1);
        System.out.println("使用辅助空间实现============");
        int []helper = new int[N];
        for (int i = 0; i < helper.length; i++) {
            helper[arr[i]]++;
        }
        for (int i = 0; i < helper.length; i++) {
            if (helper[i]==2) {
                System.out.println(i);
                break;
            }
        }
 
    }
    public static void swap(int[] array,int x,int y){
        int xx = array[x];
        int yy = array[y];
        array[x] = yy;
        array[y] = xx;
    }
 
}

二.求二进制中1的个数

 法1:通过判断32位数的每一位是否为1,为1就count++。

          这里也有两种方法去判断二进制中是否为1. 

          不带符号右移i位然后与1相与为1就说明该位为1:((N>>>i)&1)==1

          或者让1先左移i位再与数N相与看是否与1左移i位后相等:N&(1<<i)==(1<<i)

 法2:(N-1)&N的效果就是消掉最低位的1;所以就看要消几次值就变成0.

import java.util.Scanner;

public class 二进制一的个数 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
      Scanner sc = new Scanner(System.in);
      int n = sc.nextInt();
      System.out.println(Integer.toString(n, 2));
      
      int count = 0;
      for(int i=0;i<32;i++) {
    	  if((n&(1<<i))==(1<<i)){
    		  count++;
    	  }
      }
      System.out.println(count);
      System.out.println("-----------方法二------------");
      count=0;
      while(n!=0) {
    	  n=((n-1)&n);
    	  count++;
      }
      System.out.println(count);
	}

}

 三.判断一个数是不是2的整数次方

  意思就是该数的二进制只有1个1

      所以可以通过判断该数消掉最低位的1后是否为0 : if((N-1)&N)==0) 则是2的整数次方

 四.将整数的二进制交换奇偶位交换

     法1:将该数转化为二进制后,然后用for循环交换他们的奇偶位,每次前进两个步长。

     法2:先和0Xaaaaaaaa(即1010.....10)做与运算,保留偶数位,奇数位为0.

              然后与0X55555555(即0101.....01)做与运算,保留奇数位,偶数位为0.

              然后让保留下来的偶数位左移1位,保留下来的奇数位右移1位,最后相与。

public class 整数二进制奇偶位交换 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
	      int n = sc.nextInt();
	      //System.out.println(Integer.toString(n));输出是9
	      //System.out.println(Integer.toBinaryString(n));输出1001
	      //System.out.println(Integer.toString(n, 2));//自定义进制输出
	      //转二进制字符串并输出查看
	      System.out.println(自定义转二进制.printBinary(n));
	      String str = new String(自定义转二进制.printBinary(n));
	      //二进制字符串转换成字符数组
	      char[] x=str.toCharArray();
	      //遍历二进制的数组
	      /*for(int i=0;i<32;i++) {
	    	  System.out.println(x[i]);
	      }*/
	      for(int i=0;i<31;i++) {
	    	  char tem=x[i];
	    	  x[i]=x[i+1];
	    	  x[i+1]=tem;
	    	  i++;
	      }
	      System.out.println(x);
	      System.out.println("------方法二-------");
	      int ou = n&0Xaaaaaaaa; //和1010101010.。。。。。做与运算保留偶数位,奇数位为0
	      int ji = n&0X55555555;//和0101010101.。。。。做与运算保留奇数位。
	      System.out.println(自定义转二进制.printBinary((ou>>1)^(ji<<1)));
	}

}
public class 自定义转二进制 {
	public static String printBinary(int num){
		char[] x=new char[32];
		int j=31;
		for(int i = 0;i<32;i++){	     
			 x[i]=((num & (1 << j)) == 0 ? '0' : '1');
		     j--;
		}
		//return Arrays.toString(x);
		return String.valueOf(x);
		
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值