【位運算】找出陣列中,只出現一次的兩個數字
阿新 • • 發佈:2018-12-26
題目:
一個整型數組裡除了兩個數字之外,其他的數字都出現了兩次,請寫程式找出這兩個出現一次的數字。要求時間複雜度是O(n),空間複雜度是O(1).
分析:
由於限制了複雜度,所以要用異或運算來解,什麼是異或?
首先,計算機1個位元組是8位(1Byte=8bit);其次,異或運算是:兩個輸入相同時為0,不同則為1。
舉例陣列:
{2, 4, 3, 6, 3, 2, 5, 5}
核心思路:
1、陣列中全部資料異或操作後,依次對陣列中的每個元素進行異或(相同位為0,不同為1)操作,得到0000 0010。
2、倒數第二位是1,說明我們要找的那兩個只出現一次的數字,倒數第二位是不同的。
3、下面根據每個數二進位制倒數第二位是不是1來分成兩組,倒數第二位為1的是{2, 3, 6, 3, 2},倒數第二位為0的是{4, 5, 5}。
4、接下來對這兩個陣列分別進行異或操作,剩下的數字就是隻出現一次的數字。
程式碼:
public class FindOnceNum { public void find(int[] values) { if (Objects.isNull(values) || values.length < 2) { throw new RuntimeException("引數不正確"); } //resultExclusiveOR是那兩個出現一次的數字的異或值 int resultExclusiveOR = 0; int first = 0, second = 0; for (int i = 0; i < values.length; i++) { resultExclusiveOR ^= values[i]; } System.out.println("resultExclusiveOR: " + Integer.toBinaryString(resultExclusiveOR)); /* resultExclusiveOR中找到第一個為1的位的位置 resultExclusiveOR右移一位, count左移一位, 當resultExclusiveOR = 1的時候, count的值就是第一位為1的位置 */ int count = 1; while (true) { if ((resultExclusiveOR & 1) == 1) { break; } resultExclusiveOR >>= 1; count <<= 1; } System.out.println("count: " + Integer.toBinaryString(count)); //根據count分成兩組,分別找出不重複的那個數字 for (int i = 0; i < values.length; i++) { if ((values[i] & count) == 0) { first ^= values[i]; } else { second ^= values[i]; } } System.out.println(first); System.out.println(second); } public static void main(String[] args) { int[] values = {6, 2, 3, 1, 3, 2, 5, 5}; new FindOnceNum().find(values); } }