【九度OJ1351】|【劍指offer40】數組中只出現一次的數字

題目描述:
一個整型數組裏除了兩個數字以外,其餘的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。
輸入:
每一個測試案例包括兩行:
第一行包含一個整數n,表示數組大 小。2<=n <= 10^6。
第二行包含n個整數,表示數組元素,元素均爲int。
輸出:

對應每一個測試案例,輸出數組中只出現一次的兩個數。輸出的數字從小到大的順序。 java

知識點:異或運算的性質:任何一個數字異或它本身都等於0 數組

    這道題利用異或的幾個性質:任何數與其自己異或值都爲0,異或運算知足交換律。所以將一組數依次異或,若裏面只有一個只出現一次的數,其餘的數都出現兩次,則最後的結果必然是那個只出現一次的數。
    有了這個解決方法咱們就能夠解決兩個相異的數,若是可以把原數組分爲兩個子數組。在每一個子數組中,包含一個只出現一次的數字,而其餘數字都出現兩次。若是可以這樣拆分原數組,按照前面的辦法就是分別求出這兩個只出現一次的數字了。
測試

    咱們仍是從頭至尾依次異或數組中的每個數字,那麼最終獲得的結果就是兩個只出現一次的數字的異或結果。由於其餘數字都出現了兩次,在異或中所有抵消掉 了。因爲這兩個數字確定不同,那麼這個異或結果確定不爲0,也就是說在這個結果數字的二進制表示中至少就有一位爲1。咱們在結果數字中找到第一個爲1的 位的位置,記爲第N位。如今咱們以第N位是否是1爲標準把原數組中的數字分紅兩個子數組,第一個子數組中每一個數字的第N位都爲1,而第二個子數組的每一個數 字的第N位都爲0。(這兩個數字不一樣,意味着爲1的那個位是相異的) spa

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

public class Main {

	public static void find(int[] a,int result) {
		int pos = 1;
		while ((result & pos) == 0) {
			pos <<= 1;
		}
		int num1 = 0;
		int num2 = 0;
		for (int j = 0; j < a.length; j++) {
			if ((a[j] & pos) == 0)
				num1 ^= a[j];
			else
				num2 ^= a[j];
		}
		if (num1 < num2)
			System.out.println(num1 + " " + num2);
		else
			System.out.println(num2 + " " + num1);
	}

	public static void main(String[] args) throws IOException {
		StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		while (st.nextToken() != st.TT_EOF) {
			int length = (int) st.nval;
			int[] array = new int[length];
			int count = 0;
			int result = 0;
			while (count < length) {
				st.nextToken();
				array[count] = (int)st.nval;
				result ^= array[count++];
			}
			find(array,result);
		}
	}

}
相關文章
相關標籤/搜索