一枚菜鳥的leetcode刷題筆記 Day11

2021-10-17 05:22:03 字數 3505 閱讀 6444

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

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

class

solution

:def

singlenumber

(self, nums: list[

int])-

>

int:

tmp =

for n in nums:

if n in tmp:

tmp.remove(n)

else

:return tmp[

0]

用tmp記錄已訪問但未被配對的nums中的元素,題目說只有乙個元素出現一次,那麼當nums遍歷完成,tmp中剩下的就是只出現一次的元素。

注意python列表的remove方法可以實現直接移除元素,而pop只能按照移除索引移除。當列表中有多個相同元素時,remove方法移除首個。

class

solution

:def

singlenumber

(self, nums: list[

int])-

>

int:

crit =

0for n in nums:

crit ^

= n return crit

位異或我是第一次聽說,不過這法子也太秀了。

異或是指:如果a、b兩個值不相同,則異或結果為1。如果a、b兩個值相同,異或結果為0。

以下來自:通過雜湊集、按位異或操作符解決(解題思路)

舉一例例子:

甲:0 0 0 0 1 1 0 0 (值為12)

乙:0 0 0 0 0 1 1 1 (值為7)

甲和乙進行按位異或操作得到新值丙

丙:0 0 0 0 1 0 1 1 (值為11)

可見,當兩值的某一位的值不同時,按位異或操作後所得新值某一位的值將為 1 (如從右到左第一位),反之為 0 (如從右到左第三位)。

通過觀察,和結合按位異或操作符的性質我們可以發現乙個按位異或操作的性質:乙個值和0進行按位異或操作所得為該值,相同的兩個值進行異或操作,所得為0(甲 按位異或 0 得 甲,甲 按位異或 甲 得 0)。根據這個性質,由於每個重複元素重複兩次,故他們在遍歷後將相互抵消,而唯一元素只出現一次,故將得到保留。陣列 12、7、12 之所以依次按位異或結果為 7 是因為按位異或操作符滿**換律。即:

12 xor 7 xor 12

= 12 xor 12 xor 7

= 0 xor 7

= 7python自帶的異或運算^,可以分為三步:

給定乙個鍊錶,判斷鍊錶中是否有環。

class

solution

:def

hascycle

(self, head: listnode)

->

bool

: hasvisit =

while head is

notnone

:if head in hasvisit:

return

true

else

: head = head.

next

return

false

這是一版簡單解法,只需遍歷鍊錶,然後看看已遍歷的節點是否重複出現即可。

class

solution

:def

hascycle

(self, head: listnode)

->

bool

: i1,i2 = head,head

while i1 is

notnone

and i2 is

notnone

: i1 = i1.

next

i2 = i2.

next

if i2 is

notnone

:#不成環時,避免出現i2.next為none,則i2.next.next報錯

i2 = i2.

next

else

:break

if i1 == i2:

return

true

return

false

這乙個版本想用追擊法,具體為建立兩個指標,乙個一次走一步,另乙個一次走兩步。如果成環,那麼經過若干次,兩個指標一定會遇上。優點是可以計算成環的節點數目,因為兩指標第一次相遇時所走的距離差正好是環的長度。

給定乙個鍊錶,返回鍊錶開始入環的第乙個節點。 如果鍊錶無環,則返回 null。

為了表示給定鍊錶中的環,我們使用整數 pos 來表示鍊錶尾連線到鍊錶中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鍊錶中沒有環。注意,pos 僅僅是用於標識環的情況,並不會作為引數傳遞到函式中。說明:不允許修改給定的鍊錶。

高階:你是否可以使用 o(1) 空間解決此題?

class

solution

:def

detectcycle

(self, head: listnode)

-> listnode:

fast, slow = head, head

while fast:

slow = slow.

next

fast = fast.

next

ifnot fast:

return

none

else

: fast = fast.

next

if slow == fast:

break

ifnot fast:

return

none

fast = head

while slow != fast:

slow = slow.

next

fast = fast.

next

return slow

這道題目比之前的環形鍊錶的題目更難一些,還是利用雙指標,具體可參考雙指標技巧直接秒殺五道演算法題

第一次相遇時,假設慢指標slow走了k步,那麼快指標fast一定走了2k步。fast一定比slow多走了k步,這多走的k步其實就是fast指標在環裡轉圈圈,所以k的值就是環長度的整數倍。

設相遇點距環的起點的距離為m,那麼環的起點距頭結點head的距離為k - m,也就是說如果從head前進k - m步就能到達環起點。巧的是,如果從相遇點繼續前進k - m步,也恰好到達環起點。你甭管fast在環裡到底轉了幾圈,反正走k步可以到相遇點,那走 k - m 步一定就是走到環起點了。所以,只要我們把快慢指標中的任乙個重新指向head,然後兩個指標同速前進,k - m步後就會相遇,相遇之處就是環的起點了。

一枚菜鳥的leetcode刷題筆記 Day5

給你乙個鍊錶陣列,每個鍊錶都已經按公升序排列。請你將所有鍊錶合併到乙個公升序鍊錶中,返回合併後的鍊錶。class solution def merge2lists self,l1,l2 l1 and l2 are two linked lists head listnode rehead head ...

一枚菜鳥的leetcode刷題筆記 Day8

70 爬樓梯 78 子集 乙個機械人位於乙個 m x n 網格的左上角 起始點在下圖中標記為 start 機械人每次只能向下或者向右移動一步。機械人試圖達到網格的右下角 在下圖中標記為 finish 問總共有多少條不同的路徑?class solution def uniquepaths self,m...

一枚菜鳥的leetcode刷題筆記 Day14

在未排序的陣列中找到第 k 個最大的元素。請注意,你需要找的是陣列排序後的第 k 個最大的元素,而不是第 k 個不同的元素。class solution def findkthlargest self,nums list int k int int nums.sort 從小到大排列 return n...