鏈表中倒數第k個節點 & 反轉鏈表 & 合併兩個排序鏈表 & 兩個鏈表的第一個公共節點 & 鏈表中環的入口節點 & 刪除鏈表中的重複元素 & 複雜鏈表的複製

逐漸成爲靈魂畫手[doge]。。

複習鏈表:

鏈表中倒數第k個節點

class Solution:
    def FindKthToTail(self, head, k):
        # write code here, 快慢指針,k是兩個指針的相對固定舉例,當快指針到達None,慢指針就是結果
        first = head
        second = head
        
        # 讓快指針先走k步
        for i in range(k):
            if first == None:  # 注意這裏需要先判斷哦
                return None
            first = first.next
        # 當快指針到達None的時候,慢指針就是倒數第K個節點
        while first:
            first = first.next
            second = second.next
        return second

 

 

反轉鏈表:

class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        # 需要3個指針,分別指向比如第左號節點,讓它的指針指向None,
        # while 當最右邊指針指向None的時候,這時的mid節點就是新的表頭節點
        # 讓剛纔的中號節點指針指向左號
        # 向右同時移動一步,3個指針,左號變爲中,中變爲右號,右號指向下一個節點
        # 注意邊界
        if pHead == None:
            return None
        if pHead.next == None:
            return pHead
        
        leftPointer = pHead
        midPointer = leftPointer.next
        rightPointer = midPointer.next
        
        leftPointer.next = None
        
        while rightPointer != None:
            midPointer.next = leftPointer
            leftPointer = midPointer
            midPointer = rightPointer
            rightPointer = rightPointer.next
            
        midPointer.next = leftPointer  # 邊界,當只有2個節點時,不走上面的while
        return midPointer

合併兩個排序鏈表

需要 4個指針

class Solution:
    # 返回合併後列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if pHead1 == None:
            return pHead2
        if pHead2 == None:
            return pHead1
        # 指針1
        newHead = pHead1 if pHead1.val < pHead2.val else pHead2
        
        # 指針2 & 3
        tmp1 = pHead1
        tmp2 = pHead2
        
        if newHead == tmp1:
            tmp1 = tmp1.next
        else:
            tmp2 = tmp2.next
        
        # 指針4
        pre = newHead
        
        # 判斷條件,當不管誰,最後一個爲None的時候,退出循環
        while tmp1 and tmp2:
            if tmp1.val < tmp2.val:
                pre.next = tmp1
                pre = tmp1
                tmp1 = tmp1.next
            else:
                pre.next = tmp2
                pre = tmp2
                tmp2 = tmp2.next
        # 剩下最後一個節點情況,誰先到頭了,把pre鏈接到另一個剩下的節點
        if tmp1 == None:
            pre.next = tmp2
        else:
            pre.next = tmp1
        
        return newHead

 

兩個鏈表的第一個公共節點

class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        # write code here
        # 先找到2個鏈表的長度差
        # 然後讓長的鏈表先走長度差
        # 然後兩個指針同時走,當遇到相同的節點時候,那就是公共節點(注意邊界條件,兩個相同長度的鏈表)
        
        tmp1 = pHead1
        tmp2 = pHead2
        
        while tmp1 and tmp2:
            if tmp1 == tmp2:
                return tmp1
            tmp1 = tmp1.next
            tmp2 = tmp2.next
        
        if tmp1:  # 意味着tmp2先到頭,等於None
            return self.find_common(tmp1,tmp2,pHead1, pHead2)
        if tmp2:
            return self.find_common(tmp2,tmp1,pHead2, pHead1)
    
    def find_common(self, long_pointer, short_pointer, long_head, short_head):
        # 需要4個指針,2個指向兩個鏈表頭,2個分別指向鏈表節點
        # 計算K的差距
        k = 0
        while long_pointer:
            long_pointer = long_pointer.next
            k += 1
        # 先走k步
        long_pointer = long_head
        short_pointer = short_head
        for i in range(k):
            long_pointer = long_pointer.next
        # 一起走直到相等
        while long_pointer != short_pointer:
            long_pointer = long_pointer.next
            short_pointer = short_pointer.next
        return long_pointer

鏈表中環的入口節點

核心: -> 判斷是否有環(快慢指針) -> 從相遇點走單步 --> over


# 利用快慢指針判斷是否存在環,快指針走2步,慢指針走1步
# 上一個while退出條件存在2個,當爲快指針走到None,或者 快慢指針相遇都會退出,這裏是只相遇
# 所以從相遇點,快指回到pHead, 慢指針繼續走那m,第一次遇到相同的節點就是環的起點

# 囉嗦的寫法
class Solution:
    def EntryNodeOfLoop(self, pHead):
        # 運行超時了!!!該方法不行
        # write code here
        if pHead == None:
            return None
        # 利用快慢指針判斷是否存在環,快指針走2步,慢指針走1步
        fastPointer = pHead
        slowPointer = pHead
        while fastPointer and fastPointer.next:
            fastPointer = fastPointer.next.next
            slowPointer = slowPointer.next
            if fastPointer == slowPointer:
                break
        
        # 上一個while退出條件存在2個,當爲快指針走到None,或者 快慢指針相遇都會退出
        if fastPointer == None or fastPointer.next == None:
            return None
        
        # 到這裏就說明是快慢指針相遇了,需要按公式進行計算,搜索環入口節點
        # 快慢指針相遇  所以慢指針走了l,快指針走了2l
        # 慢指針環外面距離爲s,環裏走的長度爲d,環內沒走的長度爲m --> l = s + d ,  
        # 快指針走的距離爲  n*(m + d) + d + s = 2l
        # 代入公式,所以 s = m + (n-1)(m+d) ,
        # 所以從相遇點,快指回到pHead, 慢指針繼續走那m,第一次遇到相同的節點就是環的起點
        fastPointer = pHead
        while fastPointer != slowPointer:
            fastPointer = fastPointer.next
            slowPointer = slowPointer.next
        return slowPointer

# 簡潔的寫法:
class Solution:
    def EntryNodeOfLoop(self, pHead):
        if pHead == None or pHead.next == None:
            return None
        
        fast = pHead
        slow = pHead
        
        while fast.next and slow:
            fast = fast.next.next
            slow = slow.next
            
            if fast == slow:
                fast = pHead
                while fast != slow:
                    fast = fast.next
                    slow = slow.next
                return fast
        return None

 

刪除鏈表中的重複元素

class Solution:
    def deleteDuplication(self, pHead):
        # write code here
        # 邊界條件
        if pHead == None:
            return None
        
        # 需要3個指針,root,pre, cur,
        root = ListNode(0) # 爲什麼需要root指針,因爲 1->1->2 最前面需要root指針
        root.next = pHead
        pre = root
        cur = root
        
        # 判斷單個連續 1->2->2->3
        while cur:
            while cur.next and cur.val == cur.next.val:
                cur = cur.next
            # 判斷多個連續情況 1->2->2->3->3->4
            cur = cur.next
            if cur and cur.next and cur.val == cur.next.val:
                continue
            pre.next = cur
            pre = pre.next
        return root.next

複雜鏈表的複製

輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。
(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)
# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        # write code here
        self.clone_node(pHead)
        self.clone_random(pHead)
        return self.split(pHead)
    
    def clone_node(self, pHead):
        node = pHead
        while node:
            copynode = RandomListNode(node.label)
            copynode.next = node.next
            node.next = copynode
            node = copynode.next
    
    def clone_random(self, pHead):
        node = pHead
        while node:
            clone = node.next
            if node.random:
                clone.random =node.random.next
            node = clone.next
    
    def split(self, pHead):
        node = pHead
        copyhead = copynode = None
        if node:
            copyhead = copynode = node.next
            node.next = copynode.next
            node = node.next
        while node:
            copynode.next, copynode  = node.next, copynode.next
            node.next, node = copynode.next, node.next
        return copyhead

 

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