位運算-查找數組中唯一成對的數


基礎實例一使用位運算判斷數的奇偶性

  實例代碼:

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+"\t"+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);
    }
}

  

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM