《劍指Offer》——鏈表(Python3 實現)

目錄

鏈表

1、從尾到頭打印鏈表

2、鏈表中倒數第K個結點

3、反轉鏈表

4、合併兩個排序的鏈表

5、複雜鏈表的複製

6、兩個鏈表的第一個公共結點

7、鏈表中環的入口點

8、刪除鏈表中重複的結點


鏈表

1、從尾到頭打印鏈表

問題:輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList。

思路:直接遍歷一遍鏈表保存結果到list中,再返回倒序的list即可。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
    self.val = x
    self.next = None
class Solution:
    # 返回從尾部到頭部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        # write code here
        arr=[]
        while listNode:
            arr.append(listNode.val)
            listNode=listNode.next
        return arr[::-1]

2、鏈表中倒數第K個結點

問題:輸入一個鏈表,輸出該鏈表中倒數第K個結點。

思路:先計算鏈表的長度,然後計算找到倒數第k個需要幾次循環,並判其中關係。最後,用for循環,不斷將指針指向下一個節點,即爲所求。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def FindKthToTail(self,head,k):
        len_node=0
        temp=head
        while temp:
            temp=temp.next
            len_node+=1
        run_times=len_node-k
        if run_times<0 or k<0:
            return
        for i in range(run_times):
            head=head.next
        return head

3、反轉鏈表

問題:輸入一個鏈表,反轉鏈表後,輸出鏈表的所有元素。

思路:利用三個指針逐個翻轉(頭插法建立單鏈表)。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def ReverseList(self,phead):
        if not phead:
            return
        p=phead
        q=phead.next
        p.next=None
        while q:
            r=q.next
            q.next=p
            p=q
            q=r
        return p 

4、合併兩個排序的鏈表

問題:輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,需要合成後的鏈表滿足單調不減規則。

思路一:迭代方法求解。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def Merge(self,pHead1,pHead2):
        p1=pHead1
        p2=pHead2
        if p1 and p2:   #首先,判斷哪個鏈表的頭結點的值小,將值小的作爲合併後鏈表的頭結點
            if p1.val<=p2.val:
                head=p1
                p1=p1.next
            else:
                head=p2
                p2=p2.next
            r = head
        elif p1:
            return p1
        else:
            return p2
        while p1 and p2:
            if p1.val<=p2.val:
                r.next=p1
                p1=p1.next
                r=r.next
            else:
                r.next=p2
                p2=p2.next
                r=r.next
        if p1:
            r.next=p1
        if p2:
            r.next=p2
        return head

思路二:遞歸方法。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val =x
        self.next =None
class Solution:
    def Merge(self,pHead1,pHead2):
        merged=None
        if not pHead1:   #當pHead1爲空時,返回pHead2
            return pHead2
        if not pHead2:   #當pHead2爲空時,返回pHead1
            return pHead1
        #第一個鏈表中的第一個點小於第二個鏈表中的第二個點,那麼merged第一個點就是pHead1的第一個點
        #對於它的next,繼續執行遞歸
        if pHead1.val<=pHead2.val:
            merged=pHead1
            pHead1=pHead1.next
            merged.next=self.Merge(pHead1,pHead2)
        else:
            merged=pHead2
            pHead2=pHead2.next
            merged.next=self.Merge(pHead1,pHead2)
        return merged

5、複雜鏈表的複製

問題:輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)

# -*- coding:utf-8 -*-
class RandomListNode:
    def __init__(self, x):
        self.label =x
        self.next =None
        self.random=None
class Solution:
    def Clone(self,pHead):
        if not pHead:
            return pHead
        #開闢一個新結點
        copy=RandomListNode(pHead.label)
        copy.next=pHead.next
        copy.random=pHead.random
        #遞歸剩餘的結點
        copy.next=self.Clone(pHead.next)
        return copy

6、兩個鏈表的第一個公共結點

問題:輸入兩個鏈表,找出它們的第一個公共結點。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self,x):
        self.val=x
        self.next=None
class Solution:
    def FindFirstCommonNode(self,pHead1,pHead2):
        if not pHead1 or not pHead2:
            return None
        length1=0
        length2=0
        p1=pHead1
        p2=pHead2
        #分別計算兩個鏈表的長度
        while p1:
            length1+=1
            p1=p1.next
        while p2:
            length2+=1
            p2=p2.next
        #根據兩個鏈表的長度,確定長、短鏈表和它們之間的長度差
        if length1>=length2:
            step=length1-length2
            longList=pHead1
            shortList=pHead2
        else:
            step=length2-length1
            longList=pHead2
            shortList=pHead1
        #讓長鏈表先走step步
        for i in range(step):
            longList=longList.next
        #同時遍歷兩個鏈表,讓他們不斷指向next,並判斷何時相等,相等時返回任一一個鏈表即可
        while longList and shortList:
            if longList==shortList:
                return longList
            else:
                longList=longList.next
                shortList=shortList.next
        return None

7、鏈表中環的入口點

問題:一個鏈表中包含環,請找出該鏈表的環的入口點。

思路:第一步,找環中相匯點。分別用p,q指向鏈表頭部,p每次走兩步,q每次走一步,直到p==q找到在環中的相匯點。

第二步,找環的入口。接上一步,當p==q時,p所經過的節點數爲2x,q所經過的節點數爲x,設環中有n個節點,p比q多走一個環,有2x=x+n;n=x;可以看出q實際走了一個環的步數,再讓p指向鏈表頭部,q位置不變,p,q每次走一步直到p==q;此時p,q指向環的入口。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self,x):
        self.val=x
        self.next=None
class Solution:
    def EntryNodeOfLoop(self,pHead):
        if pHead==None:
            return None
        if pHead.next==None or pHead.next.next==None:
            return None
        #使用快慢指針,p每次走兩步,q每次走一步
        p=pHead.next.next
        q=pHead.next
        #第一次循環,直到p和q相遇,p每次走兩步,q每次走一步
        while p!=q:
            p=p.next.next
            q=q.next
            if p.next==None or p.next.next==None:
                return None
        #第二次循環,直到p和q相遇,讓快指針p回到開始的點,p和q每次都走一步
        p=pHead
        while p!=q:
            p=p.next
            q=q.next
        return p

8、刪除鏈表中重複的結點

問題:在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。例如,鏈表1->2->3->3->4->4->5處理後爲1->2->5。

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self,x):
        self.val=x
        self.next=None
class Solution:
    def deleteDuplication(self,pHead):
        temp=[]
        head=pHead
        #先將pHead中所有結點的value全部放到temp列表中去
        while head:
            temp.append(head.val)
            head=head.next
        result=ListNode(0)  #創建一個新的指針
        head=result   #讓head指向這個指針
        for i in temp:
            if temp.count(i)==1:  #對於temp中的元素,如果出現次數等於1就添加到head的next指針
                head.next=ListNode(i)
                head=head.next
        return result.next

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章