LeetCode 只出現一次的數字

2021-08-21 08:26:20 字數 2069 閱讀 1658

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

說明:

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

示例 1:

輸入: [2,2,1]

輸出: 1

示例 2:

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

輸出: 4

這道題思路很多,我們逐個來考慮:

1.列舉(enum pairs)。對於陣列中每個數,檢查陣列中有多少與它相同的數,如除它本身已無相同數,則返回此數(count the equals)。如[2,3,2,3,4]中僅有4無相同數。o(n²)級的效率,比較慢。

2.剔除(remove the equals),基於列舉演算法。列舉中相同的數進行了兩次同樣的掃瞄,浪費了較多時間。同樣進行順序掃瞄,我們可以在掃瞄時發現相同的數就從陣列中剔除。

[>2,3,2,3,4]: ( # 表示掃瞄到這)

[#2,  3,  2,  3,  4] ——    [#2,  3,  4,  3]

[ 2, #3, 4, 3] —— [ 2, #3, 4]

[ 2, 3, #4] —— 結果為 4

o(n²)級的效率,仍然比較慢。

3.快排(quicksort)。萬金油一般的解法,如[2,3,2,3,4]排序後就是[2,2,3,3,4],然後檢查,如果此數與後一數相同,就跳過這兩個數,直到找到為止。o(nlogn)級的效率,較為一般,還可以更快。

4.二分(divide&conquer)。建立在快排(qsort)的基礎上。快排的思路是根據基準數(pivot)將陣列分為左小右大兩部分,每次將基準數歸位。這裡也可以採用同樣的思路,除了分為兩部分,同時還遞迴檢查陣列中有沒有相同的數。如果劃分成大小兩部分之後,某一邊發現它的基準數隻出現一次,那肯定就是它了,因為其他分割槽的數和它存在大小關係,不可能與它相等(left is less and right is larger, neither equals)。這相當於在排序完成之前就找到了結果,效率會稍高一些。o(nlogn)級的效率,好一點,還能快。

5.桶排(bucketsort)。先掃一次找最小值最大值,然後逐個數入桶,最後找只有乙個入數的桶。需要較大空間來換取o(n)的時間。

6.桶排空間優化(bucketoptimizing)。由於我們只需要在陣列中找奇數次出現的數而忽略偶數次的(find odd),所以我們可以將桶設為bool型別的,最後找值為true的桶。

x

^ x = 0

x^0 = x

x^ y^ y = x^

0 = x

即:對數x進行兩次xor y,得到的結果仍是x。

有了這個性質,我們便可以輕鬆發現,將陣列中所有數異或一次,最後剩下的數就是我們要找的數了。

為了卡進4ms用了指標,不過應該理解起來也不算很難吧

int singlenumber(int* nums, int numssize)
這個應該算是目前為止最合適的演算法了。

拓展:如果是兩個數出現奇數次呢,三個數呢?

只出現一次的數

給定乙個整數陣列 nums,其中恰好有兩個元素只出現一次,其他所有元素均出現兩次。找出只出現一次的那兩個元素。示例 給定 nums 1,2,1,3,2,5 返回 3,5 注意 結果的順序並不重要,對於上面的例子 5,3 也是正確答案。你的演算法應該具有線性複雜度,你能否僅使用恆定的空間複雜度來實現它...

只出現一次的數

問題描述 給定乙個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。解決思路 將陣列中元素全部異或,根據異或特點,出現兩次的元素異或後結果為0,陣列全部異或之後的結果就是只出現一次的那個元素。實現 int singlenumber vector int n...

只出現一次的數

問題 有n個數,其中只有乙個數出現一次,其他的都出現兩次,求這個數 空間複雜度為常數 全部xor起來即可 include includeusing namespace std int main printf d n xor sum return 0 1231 3 1 51 2 3 2 3 inclu...