尋找陣列中唯一出現兩次的數

2021-07-02 17:39:57 字數 1615 閱讀 3812

假設你有乙個用1001個整數組成的陣列,這些整數是任意排列的,但是你知道所有的整數都在1到1000(包括1000)之間。此外,除乙個數字出現兩次外,其他所有數字只出現一次。假設你只能對這個陣列做一次處理,用一種演算法找出重複的那個數字。如果你在運算中使用了輔助的儲存方式,那麼你能找到不用這種方式的演算法嗎?

第一種方法:

如果允許使用額外的空間,那就比較好吧,這些數,只有乙個出現了兩次,其他都只出現一次,那麼,我們就用個陣列來統計一下每個數出現的次數,在統計過程中,如果出現乙個是出現2次的話,那麼毫無疑問,程式可以結束了,返回相應的數字即可。由於我們只需要遍歷陣列一次,所以時間複雜度是o(n)

優點:效率高

缺點:消耗的記憶體空間過大

關於空間的,本人在這裡有個疑問,如果有人能為我解惑,那麼將感激不敬。

空間複雜度到底是o(1)還是o(n)?我們定義的陣列是n個元素,所以我理所當然地覺得空間複雜度是o(n),但是曾在一些書籍上面看到,由於n是確定的,所以相當於是恒量空間,所以空間複雜度是o(1),到底是哪個我也不清楚,希望有人能為我解惑。

int findrepeat(int a)

;for(int i=0;i<=1000;i++)

else  }

} 根據這種使用額外陣列做標記的方法,並且考慮到元素的特殊性,只有乙個是出現了兩次,那麼我們其實可以不用統計次數,而是簡簡單單地做下標記即可,比如說,我們可以定義乙個bool型的陣列,全部初始化為false,進行遍歷的時候,相應的元素如果出現就將其設定為true,當乙個標記是true,卻再次掃瞄到該元素的時候,那麼則該元素出現了兩次了,乙個bool型占用的記憶體空間是乙個位元組,而int型別占用的記憶體是4個位元組,這樣子,占用的空間已經大大地減少了。那麼是否還有類似的辦法,但是占用的記憶體空間更少的呢?true和false僅僅只是兩個值,考慮到計算機的位,無非也就0,1兩種值,所以我們可以使用位來進行標記,於是便要使用到了點陣圖資料結構這種東西了(關於位圖資料結構,我前面有一篇文章,可以參考參考)1000位,8位就是乙個位元組,1000位等於125位元組,所以可用32個int型別來表示,這樣子記憶體空間已經大大減少了。

第二種方法:

雖然第一種解法到最後我們能大大地減少記憶體空間,不過還是占用了一定的記憶體空間,面試中面試官估計還是不會這麼善罷甘休的,肯定希望我們再減少空間的使用。第二種方法主要用到的是數學的知識,1001個數,有乙個出現了兩次,那麼我把這1001個數加起來,用和減去1到1000的和,很明顯,差就是出現了兩次的那個數了。

int findrepeat(int a)

for(int j=1;j<=1000;j++)

return sum1-sum2;}

優點:記憶體空間消耗很少,

缺點:由於這種方法要完全遍歷陣列,所以效率要低於第一種方法,除非很不巧,重複是出現在最末尾。

第三種方法:

這種方法主要使用到了位運算,其實位運算有很多有用的性質,只是為人們所不熟悉罷了。

這裡主要用到的是異或運算的性質,a^a^b=b,以及異或運算滿足結合律和交換律

將1001個數進行異或,結果與1到1000異或的結果進行異或,得到的值即為所求。

看個簡單的例子吧

1,2,3,4,4,5

1,2,3,4,5

看出玄機了吧,其實就是相當於我們手動為第乙個陣列構造乙個副本,以便發揮a^a^b=b的性質。

唯一出現兩次的數字

今天mayuyu遇到了一道很難的數學題,人家本來就不擅長數學嘛!在的幫助下,mayuyu順利解決了它。mayuyu的問題是這樣的 給定乙個長度為100000的整數陣列,沒有排過序,所有整數的範圍均在int內,除了其中乙個數字出現過2次 以 外,其餘 的數字都出現過3次,現在要mayuyu找出唯一出現...

陣列中唯一出現1次的數 唯一出現2次的數

題目 乙個整型陣列裡除了1個數字之外,其他的數字都出現了兩次,請寫程式找出這個只出現一次的數字。要求時間複雜度是 o n 空間複雜度是 o 1 例如輸入陣列 2,4,3,3,2,5 因為只有 4 這個數字只出現一次,其他數字都出現了兩次,所以輸出 4 分析 本題以及延伸題目,在劍指offer上有詳細...

資料結構演算法題 尋找陣列中唯一出現兩次的數

假設你有乙個用1001個整數組成的陣列,這些整數是任意排列的,但是你知道所有的整數都在1到1000 包括1000 之間。此外,除乙個數字出現兩次外,其他所有數字只出現一次。假設你只能對這個陣列做一次處理,用一種演算法找出重複的那個數字。如果你在運算中使用了輔助的儲存方式,那麼你能找到不用這種方式的演...