1. 程式人生 > 其它 >leetcode(12)連結串列系列題目

leetcode(12)連結串列系列題目

21. 合併兩個有序連結串列

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        if not list1:
            return list2
        if not list2:
            return list1
        if list1.val < list2.val:
            list1.next = self.mergeTwoLists(list1.next, list2)
            return list1
        else:
            list2.next = self.mergeTwoLists(list1, list2.next)
            return list2

23. 合併K個升序連結串列

思路 1:
歸併,分而治之
連結串列兩兩合併

class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        if not lists:
            return 
        n = len(lists)
        return self.merge(lists, 0, n - 1)
    def merge(self, lists, left, right):
        if left == right:
            return lists[left]
        mid = (left + right) // 2
        l = self.merge(lists, left, mid)
        r = self.merge(lists, mid + 1, right)
        return self.mergeTwo(l, r)
    def mergeTwo(self, l1, l2):
        if not l1:
            return l2
        if not l2:
            return l1
        if l1.val < l2.val:
            l1.next = self.mergeTwo(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwo(l1, l2.next)
            return l2

思路 2:
呼叫優先順序佇列,實現最小堆
時間複雜度:O(n∗log(k)),n 是所有連結串列中元素的總和,k 是連結串列個數。

class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        import heapq  #呼叫堆
        minHeap = []
        for l in lists:
            while l:
                heapq.heappush(minHeap, l.val)  #把l中的資料逐個加到堆中
                l = l.next
        dummy = ListNode(0)
        p = dummy  #構造虛節點
        while minHeap:
            val = heapq.heappop(minHeap) #依次彈出最小堆的資料
            p.next = ListNode(val)
            p = p.next
        return dummy.next

206.反轉連結串列

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre, cur = None, head
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        return pre

25. K 個一組翻轉連結串列

class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        cur = head
        for _ in range(k):
            if not cur:
                return head  # 如果head後續節點數不足k個直接返回head
            cur = cur.next
        
        pre, cur = None, head
        for _ in range(k):  # 將包括head往後的k個節點翻轉
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        
        head.next = self.reverseKGroup(cur, k)  # 遞迴得到下一段k個節點的反轉後的頭結點
        # head已經是當前段k個節點的尾節點了,指向下一段的反轉後的頭結點
        return pre

24. 兩兩交換連結串列中的節點

class Solution:
    def swapPairs(self, head: ListNode) -> ListNode:
        res = ListNode(next = head)
        pre = res
        while pre.next and pre.next.next:
            cur = pre.next
            tmp = pre.next.next

            cur.next = tmp.next
            tmp.next = cur
            pre.next = tmp
            pre = pre.next.next
        return res.next

92. 反轉連結串列 II

class Solution:
    def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
        # 設定 dummyNode 是這一類問題的一般做法
        # dummy = ListNode(-1)
        # dummy.next = head
        dummy = ListNode(next = head)  # 等價於
        pre = dummy
        for _ in range(left - 1):
            pre = pre.next

        cur = pre.next
        for _ in range(right - left):
            next = cur.next
            cur.next = next.next
            next.next = pre.next
            pre.next = next

        return dummy.next

143.重排連結串列

203. 移除連結串列元素

劍指 Offer 18. 刪除連結串列的節點

劍指 Offer 22. 連結串列中倒數第k個節點

19. 刪除連結串列的倒數第 N 個結點

劍指 Offer 06. 從尾到頭列印連結串列

劍指 Offer 35. 複雜連結串列的複製

141. 環形連結串列

142. 環形連結串列 II

160. 相交連結串列

參考資料:
從遞迴到迭代:由淺入深……