1. 程式人生 > >leetcode筆記-連結串列

leetcode筆記-連結串列

反轉連結串列

cur 記錄要處理的節點 pre 記錄cur前一個節點 實際上始終是初始狀態下的第一個節點 每次將cur.next更改為頭節點,並更新head

    def reverseList(self, head):
        if head == None or head.next == None:
            return head

        pre = head
        cur = pre.next

        while not cur == None:

            pre.next = cur.next
            cur.next = head

            head = cur
            cur = pre.next

        return
head

兩數相加

兩個連結串列有一樣長,或一長一短兩種情況 先處理一樣長的部分 如果連結串列L2未處理完,L1一定已處理完 再處理接下來的部分 當所有節點處理完後,可能出現進位的情況 最後判斷一次是否有進位

def addTwoNumbers(self, l1, l2):
        e = 0
        p = l1
        q = l2
        t = None
        while p and q:
            p.val = (p.val+q.val+e)
            e = p.val//10
            p.val = p.val%10
t = p p = p.next q = q.next if q != None: p = t p.next = q p = p.next while p: p.val = p.val+e e = p.val//10 p.val = p.val%10 t = p p = p.next if e ==1
: p = t p.next = ListNode(1) return l1

合併兩個有序連結串列

1.兩個連結串列均未處理完 2.其中一個連結串列未處理的部分節點

    def mergeTwoLists(self, l1, l2):
        cur = ListNode(0)
        head = cur
        while l1 and l2:
            if l1.val < l2.val:
                cur.next = l1
                cur = cur.next
                l1 = l1.next
            else:
                cur.next = l2
                cur = cur.next
                l2 = l2.next
        if l1!=None:
            cur.next=l1
        if l2!=None:
            cur.next=l2
        return head.next

合併k個有序連結串列

一開始選擇和合並兩個有序連結串列一樣的思路,每次從k個鏈中選出最小節點。連結串列個數為m,節點總數為n,時間複雜度O(n*m) 只有兩個連結串列時,建立連結串列的過程即可對大小進行判斷,時間複雜度O(n) 對於多個連結串列可以先遍歷一遍然後排序,建立新連結串列。節點個數為n,三個階段時間複雜度分別為O(n),O(nlogn),O(n) 注意對節點陣列中空元素的處理

def mergeKLists(self, lists):
        ret = []
        if len(lists) == 0:
            return None
        for x in lists:
            while x:
                ret.append(x.val)
                x = x.next
        if len(ret)==0:
            return None
        ret.sort()
        head = ListNode(ret[0])
        cur = head
        for n in ret[1:]:
            cur.next = ListNode(n)
            cur = cur.next
        return head

旋轉連結串列

將連結串列成環,從新走過k-n個節點,修改頭節點位置,斷鏈 注意:1.空連結串列 2 k大於n時需要取餘 由於 k可能大於連結串列長度 所以至少要遍歷一次 求的連結串列長度n 共訪問2n-k次 也可以參考旋轉陣列,整個翻轉連結串列,然後反轉前k個節點,再反轉後k個節點 訪問2n次

def rotateRight(self, head, k):
        if head == None:
            return None
        cur = head
        n=1
        while cur.next!=None:
            n+=1
            cur = cur.next
        cur.next = head
        k = k % n
        n = n-k
        while n>0:
            cur = cur.next
            n-=1
        head = cur.next
        cur.next = None
        return head

環形連結串列

如果連結串列有環,當指標進入環後 就會無限迴圈 設定快慢指標 步長為1,2 變為一個追擊問題如果追得上 則有環。 如果出現一方到達終點(指標為空)則無環

    def hasCycle(self, head):
        slow = head
        fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                return True
        return False

環形連結串列 II

將連結串列分為無環部分m和有環部分n 快指標每次前進比滿指標多1,相遇時正好多n 則迴圈次數=環長度 相遇時,慢指標走過m和部分環c 快指標走過 m+n+c m+n+c = 2(m+c) 所以m+c部分正好等於環長度 所以m長度等於相遇點到環起點的長度

    def detectCycle(self, head):
        slow = head
        fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                p = head
                while p!=slow:
                    p = p.next
                    slow = slow.next
                return p
        return None

相交連結串列

兩個連結串列 a,b 分為獨有部分LA,LB和公共部分C 從a開始經過 LA-C-LB-C 從b開始經過 LB-C-LA-C 最終會同時到達C 找到第一個公共節點

    def getIntersectionNode(self, headA, headB):
        heada = headA
        headb = headB
        while heada!=headb:
            heada = headB if heada == None else heada.next
            headb = headA if headb == None else headb.next
        return heada

刪除連結串列中的節點

    def deleteNode(self, node):
        node.val = node.next.val
        node.next = node.next.next
        node = node.next