1. 程式人生 > >【位運算】找出陣列中,只出現一次的兩個數字

【位運算】找出陣列中,只出現一次的兩個數字

題目:

一個整型數組裡除了兩個數字之外,其他的數字都出現了兩次,請寫程式找出這兩個出現一次的數字。要求時間複雜度是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);
    }
}