Java 實現陣列中只出現一次的數字
阿新 • • 發佈:2019-01-24
一個整型數組裡除了兩個數字之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。
程式碼
解法一
比較笨,先排序,是的相同的數字挨在一起,這樣不同的數字必然和前後數字都不一致,對於陣列的第一個和最後一個元素,則需要單獨處理。
public static List<Integer> findSignleAppearNumber(int[] array) { if (array == null || array.length <= 1) { return null; } // 如果陣列的長度是奇數,不可能出現兩個只出現一次的數字 if (array.length % 2 == 1) { return null; } List<Integer> result = new ArrayList<>(2); if (array.length == 2) { for (int i : array) { result.add(i); } return result; } // 對陣列排序,使得出現兩次的數字可以挨著 Arrays.sort(array); // 根據前面的判斷條件,此時陣列長度大於等於4 // 如果第一個數字和第二個數字不相等,說明第一個數字就是隻出現一次的數字 if (array[0] != array[1]) { result.add(array[0]); } // 為了和前後數字對比,第一個數字和最後一個數字不比較 for (int i = 1; i < array.length - 1; i++) { // 如果一個數字和其前後兩個數字都不相等,說明該數字只出現一次 if (array[i] != array[i - 1] && array[i] != array[i + 1]) { result.add(array[i]); } } // 如果遍歷沒有找到,說明陣列的最後一個數字是要找的 if (result.size() < 2) { result.add(array[array.length - 1]); } return result; } public static void main(String[] args) { int[] array = {1, 2, 2, 3}; List<Integer> list = findSignleAppearNumber(array); for (Integer i : list) { System.out.println(i); } }
解法二
藉助異或,任何一個數字異或它自己都等於0,只有都為0或者都為1,才為1,如果不相同則為0
public static List<Integer> findSignleAppearNumber2(int[] array) { if (array == null || array.length <= 1) { return null; } // 如果陣列的長度是奇數,不可能出現兩個只出現一次的數字 if (array.length % 2 == 1) { return null; } List<Integer> result = new ArrayList<>(2); if (array.length == 2) { for (int i : array) { result.add(i); } return result; } // 任何一個數字異或它自己都等於0,所以xor的結果是兩個只出現一次的數字的異或結果 int xor = 0; for (int i = 0; i < array.length; i++) { xor ^= array[i]; } // 找出這個異或結果二進位制第一次位為1的位置 // 以此來將原陣列切割為兩個子陣列,每個子陣列包含一個只出現一次的數字 // 因為位為1,說明兩個數字在該位上不相同,即必然一個在該位上是0,另一個是1,這是異或的規則所致 // 所以以此來劃分陣列,兩個數字必然在不同子陣列之中 int bitIndex = findFirstBitIs1(xor); int n1 = 0; int n2 = 0; for (int i = 0; i < array.length; i++) { if (is1OfBitIndex(array[i], bitIndex)) { n1 ^= array[i]; } else { n2 ^= array[i]; } } result.add(n1); result.add(n2); return result; } /** * 找出數字的二進位制上位為1的第一次出現位置 * @param n * @return */ private static int findFirstBitIs1(int n) { int bitIndex = 0; while ((n & 1) == 0) { // 如果當前位不是1,則右移一位 n = n >> 1; bitIndex++; } return bitIndex; } /** * 判斷當前數字的第index位是否是1 * @param n * @param index * @return */ private static boolean is1OfBitIndex(int n, int index) { n = n >> index; return (n & 1) == 0; }