1. 程式人生 > >LeetCode 136.Single Number(只出現一次的數字)

LeetCode 136.Single Number(只出現一次的數字)

題目

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

說明
你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?

示例1

輸入: [2,2,1]
輸出: 1

示例2

輸入: [4,1,2,1,2]
輸出: 4

難度係數: 簡單

解題思路一

常規方法是,遍歷陣列,然後統計每個值出現的次數,最後在選擇出現次數為1的那個值.該演算法的時間複雜度為O(N),首先是統計陣列,此時要遍歷整個陣列,然後是要遍歷我們的統計陣列,此時有事一個O(N),由於我們使用了一個統計陣列來儲存每個值出現的次數,此時需要的空間複雜度為O(n),因此不符合要求.

解題思路二

為了解決不需要額外的空間這個要求,我們可以使用位操作中的異或規則來進行處理.異或運演算法則如下

  1. a \oplus a = 0, a \oplus 0=a
  2. a \oplus b = b \oplus a
  3. a \oplus b \oplus c = a \oplus (b \oplus c) = a \oplus (c \oplus b) = (a \oplus b) \oplus c

其中,第一條規則說明,當某個數出現兩次時,通過 \oplus 變為0,出現一次時依然保持原來的數,第二、三條的交換律和分配律說明通過多次 \oplus

操作最終解決本題。

注意: 本體題目中指出除了某個元素值出現一次外其餘的均出現兩次,根據法則一可以看出本演算法只適合除了某個元素出現一次外,其餘元素出現偶數次的情況。

比如在示例二中的 \oplus 操作:

41212=41122=4(11)(22)=4 \begin{aligned} 4 \oplus 1 \oplus 2 \oplus 1 \oplus 2 &= 4 \oplus 1 \oplus 1 \oplus 2 \oplus 2 \\ &= 4 \oplus (1 \oplus 1) \oplus (2 \oplus 2)\\ &=4 \end{aligned}

Java實現程式碼

/**
 * @author Maosong Ran
 * @date 2018/10/06
 * @email [email protected]
 */
public class LeetCode_136 {
    public int singleNumber(int[] nums) {
        int result = 0;
        int len = nums.length;
        for (int i=0; i < len; ++i)
            result ^= nums[i];
        return result;
    }

    public static void main(String[] args) {
        LeetCode_136 leetCode = new LeetCode_136();
        System.out.println(leetCode.singleNumber(new int[]{2, 2, 1}));
        System.out.println(leetCode.singleNumber(new int[]{4, 1, 2, 1, 2}));
    }
}

輸出:

1
4

致謝