這是乙個簡單的鍊錶操作問題,在leetcode上面有52.7%的通過率,難度是簡單。但是還是想在這裡基於python做一下總結,順便總結一下鍊錶的各種操作。
首先先看一下leetcode上面的題目:
反轉乙個單鏈表。看完了題目,很直白,就是轉過來。我們嘗試對這道題進行解決。這道題用python至少會有三種解決方案。示例:輸入: 1->2->3->4->5->null
輸出: 5->4->3->2->1->null
高階:你可以迭代或遞迴地反轉鍊錶。你能否用兩種方法解決這道題?
首先是鍊錶的資料結構定義:
# definition for singly-linked list.
class
listnode
:def
__init__
(self, x)
: self.val = x
self.
next
=none
將鍊錶遍歷進list中,然後利用切片反轉list,再將list填充到鍊錶中即可。這是最簡單的一種思考邏輯,但是也比較消耗效能。時間和空間複雜度都為o(n)。
def
loop
(head)
: temp =
while head is
notnone
: head = head.
next
temp = temp[::
-1]for i, n in
enumerate
(temp)
:if i +
1<
len(temp)
: n.
next
= temp[i +1]
else
: n.
next
=none
return temp[0]
if temp else
none
另一種迭代演算法,是一種純粹交換的迭代,筆者這裡擷取了leetcode速度最快的一種。
def
reverselist
(head)
:"""
:type head: listnode
:rtype: listnode
"""ifnot head:
return
none
it = head; jt = head.
next
it.next
=none
while jt:
tmp = it
it = jt
jt = jt.
next
it.next
= tmp
return it
這一波交換操作,我們可以畫個示意圖就知道他的交換是一種怎麼樣的交換。
從圖中可以看出,迴圈的作用就是將反向指標進行儲存。同時令將指標轉向的功能。
最後一種方案是採用遞迴的方式進行鍊錶反轉。這種方式也需要一定的理解。我們先展示一下**。
def
reverselist
(head)
:"""
:type head: listnode
:rtype: listnode
"""if head is
none
or head.
next
isnone
:return head
end = reverselist(head.
next
) head.
next
.next
= head
head.
next
=none
return end
這種解法其實理解起來只有兩部分內容,傳遞反向指標和進行指標反向拼接。我們先來理解一下指標反向拼接這個操作。
1 -> 2 -> 3 -> 4 -> none
依次:3(head) -> 4(head.next) -> 3(head.next.next)
3 -> none
如此迴圈即可將鍊錶反轉過來。但是還有個關鍵就是將最後乙個指標傳遞出來。我們可以看到之前的**中,end傳出來後是一直沒有做任何操作的。不停的return出最後乙個指標。所以就將最後乙個指標傳遞了出來。
以上就是鍊錶反轉的3中方法。除此之外還想寫一些鍊錶的簡單操作。
何為快慢指標,即對鍊錶進行兩個不同步頻的指標標記遍歷。最經典的是慢指標走一步,快指標走兩步。
快慢指標有很多的應用,比如說:
判斷乙個鍊錶是否存在環。
def
hascycle
(head)
:"""
:type head: listnode
:rtype: bool
"""if head is
none
or head.
next
isnone
:return
false
fast, slow = head.
next
.next
, head.
next
while fast is
not slow:
if fast is
none
or fast.
next
isnone
:return
false
fast = fast.
next
.next
slow = slow.
next
return
true
兩個指標併排走,如果有環的話快指標最終會指向慢指標的位置。沒有環的話,快指標會指向none後退出。
當然這道題的解法不止這一樣,還可以利用set進行判斷。
輸出鍊錶中的倒數第k個節點
這道題利用快慢指標的思路是這樣的。定義兩個指標,第乙個指標向前走k-1步;第2個指標保持不動;到第k步時第2個指標也開始移動。由於兩個指標始終保持著k-1的距離,所以當快指標到達末尾時,慢指標剛好指向倒數第k個。
def
count_back
(head, k)
:if head is
none
:return head
fast, slow = head, head
for i in
range
(k -1)
: fast = fast.
next
if fast is
none
:return
none
while fast is
notnone
: fast = fast.
next
slow = slow.
next
return slow
這是關於鍊錶的兩種比較簡單的操作,反轉和快慢指標。挺常見的面試題,在這裡做一些記錄分享。 關於鍊錶的一些總結
1.在鍊錶頭部新增空頭以消除頭部特殊判斷比較常見,用於刪除和新增元素,啞結點的意思就是在head第乙個節點之前設立乙個節點。2.因為鍊錶的操作有限,所以很多時候我們可以把鍊錶中的元素儲存在陣列中,進行操作。3.鍊錶從前往後遍歷元素簡單,但是從後往前遍歷元素確實困難重重,所以我們可以使用棧來儲存資料,...
關於鍊錶操作程式設計實現的一些總結
鍊錶是一種物理儲存單元上非連續 非順序的儲存結構,資料元素的邏輯順序是通過鍊錶中的指標鏈結次序實現的。鍊錶由一系列結點 鍊錶中每乙個元素稱為結點 組成,結點可以在執行時動態生成。每個結點包括兩個部分 乙個是儲存資料元素的資料域,另乙個是儲存下乙個結點位址的指標域。使用鍊錶結構可以克服陣列需要預先知道...
鍊錶的一些操作
判斷兩個鍊錶是否有交點 判斷兩個單鏈表是否相交,如果相交,給出相交的第乙個點 假設兩個鍊錶都不存在環 相交的煉表示意圖如下所示。兩個沒有環的鍊錶如果是相交於某一結點,如上圖所示,這個結點後面都是共有的。所以如果兩個鍊錶相交,那麼兩個鍊錶的尾結點的位址也是一樣的。程式實現時分別遍歷兩個單鏈表,直到尾結...