• 位运算-查找数组中唯一成对的数


    基础实例一使用位运算判断数的奇偶性

      实例代码:

    public class Test {
    	public static void main(String[] args) {
    		System.out.println(isOdd(49));
    		System.out.println(isOdd(50));
    	}
    	//  与运算
    	public static boolean isOdd(int i){
                 return (i & 1) != 0;   // 奇数最后一位二进制为 1,偶数最后一位二进制为 0
    	}
    }
    

    基础实例二:位运算判断一个数转为二进制后的第i位数是0还是1

      实例代码:

    public class Test {
    	public static void main(String[] args) {
            // 与运算   int x = 85; System.out.println("x的第五位二进制位的数为:" + ((((x&(1<<4))>>4)==1)?"1":"0")); // 比如85的二进制为1010101,我们将它的二进制与1向左移4位来做与运算 // 就是 1010101 & 0010000 得出结果0010000 再右移4位 即可得出结果 } }

    基础实例三:位运算交换两个整数变量的值

      实例代码:

    public class Test {
    	// 异或运算
    	public static void main(String args[]){
            int a=10;int b=20;
            a=a^b;
            b=b^a;
            a=a^b;
            System.out.println(a+"	"+b);
            // 异或运算性质 x ^ x ^ y == y,因为x ^ x == 0,0 ^ y == y
        }
    }
    

    基础实例四:使用位运算,不用判断语句,求整数的绝对值

      实例代码: 

    public class Test {
    	// 异或运算
    	public static void main(String args[]){
    		System.out.println(my_abs(-53));
    		System.out.println(my_abs(53));
        }
    	public static int my_abs(int a){
    		/**
    		 * 对一个数进行位运算,是在这个数的补码上运行的
    		 * 正数的补码是原码,负数的补码为原码除了最高的符号为,取反,然后加一
    		 * int 型,先右移31位取符号位 如果a位正数,i=0;a为负数,i=-1
    		 * 一个数与-1即与0xFFFFFFFF异或就相当与取反
    		 * 因此,a与i异或后再减i(因为i为0或-1,所以减i即是要么加0要么加1)也可以得到绝对值
    		 */
    		int i = a >> 31;
    		return ((a ^ i) -i);
    	}
    }
    

    异或运算特点:

      

    题目一:找出唯一成对的数

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

      解题思路:这里使用的原理是连续的数字异或可以消除重复,A ^ A=0,( A ^ A ) ^ B ^ ( C ^ C ) =B,但是我们的题目有两个元素重复,假如使用一次异或那么这个重复的元素就会被消掉了。所以这里有一个小技巧,就是使用两次异或,先对不包含重复值数组进行异或,在对包含重复值的数组进行异或,这样下来,就相当于除了重复值每个值都异或了两次,而重复的值异或了三次,这样异或下来,就只剩一个重复的值了,就成功找出来了。为了方便测试,这里只使用了11个元素的数组,自行改成1001即可(示例代码也给出了使用辅助存储空间的解法)。这里有一个特殊的点,就是这里给出了数组是1-1000连续的数并且只有唯一一个元素值重复,所以才能构造进行异或两次的解法。

      实例代码:

    import java.util.Random;
    
    public class 唯一成对的数 {
    
    	public static void main(String[] args) {
    		
    		int N = 11;
    		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;
    	}
    
    }
    

      运行结果:

        

    题目二:找出落单的那个数

      一个数组里除了某一个数字之外,其他的数字都出现了两次。请写出程序找出这个只出现一次的数字。

      解题思路:这个题目经过上一个题目的学习,就很简单了,直接进行异或即可。

      实例代码:

    public class Test {
    	// 异或运算
    	public static void main(String args[]){
    		int []a = {1,1,2,2,3,4,3};
    		int x1 = 0;
    		for (int i = 0; i < a.length; i++) {
    			x1 = x1 ^ a[i];
    		}
    		System.out.println(x1);
        }
    }
    

      

      

  • 相关阅读:
    二维码
    struts2 result type=(chain、dispatcher、redirect、redirect-action)
    hibernate bean注解
    js uploadify
    2进制转化成字符串
    server.xml
    html css
    页面乱码
    java class 路径问题
    table th td 宽度
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/10247283.html
Copyright © 2020-2023  润新知