對應每一個測試案例,輸出數組中只出現一次的兩個數。輸出的數字從小到大的順序。 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); } } }