給定乙個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?示例 1
輸入:[2,2,1]示例 2輸出:1
輸入:[4,1,2,1,2]題目拿來一看要求:線性時間複雜度,基本確定需要用hash表,由於我跑的是python3的**,python中對hashmap的實現是dict型別,理論上(最理想狀態下)可以保證key的查詢時間在o(1)。輸出:4
思考:這裡回頭想了想,為何hashmap的查詢會如此迅速:list: 首先回顧在c語言中有乙個陣列a,如果我們採用引用傳遞,那我們寫a這個變數其實就代表我們在寫&a[0]也就是陣列a的首元素的位址,如果我們想對取得陣列a中的某下標的元素,編譯器會從a的初始下標開始,在依次讀取下乙個元素時,對位址進行相加。
(具體加多少,根據陣列的元素型別決定,這同時也和cpu有關)所以python中如果取list內的某個元素,計算機必須從陣列首位址開始逐個加上去,時間上相當於對陣列進行遍歷。
hashmap:雜湊表不會從頭遍歷,當在python中新建乙個dict名為h並向其中填充值,填充的時候,他們的位址就已經指定了,這是通過雜湊函式對映辦到的。
(注意這裡的同乙個h內的元素可能並不像陣列一樣在一段連續的記憶體中)具體的f函式不詳盡介紹,雜湊對映的方法也有很多。能保證的就是,當我們查詢dict內的某個元素時,我們可以直接得到該元素在記憶體中的位址,而不需要從某乙個首位址逐一加上去,所以在沒有發生hash碰撞的理想狀態下,hashmap的時間複雜度是線性的。
class solution:
def singlenumber(self, nums: list[int]) -> int:
record = {} #用來儲存和查詢用的dict
for i in nums:
#遍歷陣列,只要可以在dict中找到,就彈出,證明該元素並不唯一,如果沒有就記錄下來。
if i in record:
record.pop(i)
else:
record[i] = i
for i in record:
return i
題目中有另乙個高階要求是不使用額外空間,此題我們因為需要儲存我們遍歷過的數字所以才需要hash表,如果不使用hash表,表明我們必須讓數自己具有儲存和檢測的能力。leetcode上的最優回答採用了位運算的模式進行,位運算的思想滲入到微觀層面,給我們解決問題的思路開啟了新的渠道。
class solution:
def singlenumber(self, nums: list[int]) -> int:
single_num = 0
for i in nums:
single_num ^= i
return single_num
這裡通過位與位之間的異或運算實現了數字本身的儲存和查詢功能,可以看到,我們只定義了乙個變數其值為0,然後依次與陣列中每個元素相異或並賦值即可。
思考:位運算的思想十分微觀和巧妙,都是從計算機背後的執行規律上摸索來的,高階語言編譯後終將成為機器語言,巧妙利用機器語言的特性,利用記憶體等計算機體系的關係才能寫出真正好的**。異或:不同為1,相同為0。(只有1和0異或的結果才是1)
假設我們對[4,1,1]這個list進行操作,其實異或的儲存功能是在位運算上體現的,因為只要出現過1的位置與0進行異或結果都為1,這就儲存了1,由於題目中說明陣列中只有乙個值是唯一的,所以其餘位出現過的1由於異或次數是偶數次,所以根據相同位零其最後的運算結果都是0,所以最後結果的值一定是那個只出現一次的數字。
碼了!
只出現一次的數
給定乙個整數陣列 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...