美文网首页leetcode算法
leetcode链表之重排链表

leetcode链表之重排链表

作者: 小奚有话说 | 来源:发表于2022-03-28 08:41 被阅读0次

    143、重排链表

    题目:

    给定一个单链表 L 的头节点 head ,单链表 L 表示为:

    L0 → L1 → … → Ln - 1 → Ln
    

    请将其重新排列后变为:

    L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
    

    不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

    示例1:

    输入:head = [1,2,3,4]
    输出:[1,4,2,3]
    

    示例2:

    输入:head = [1,2,3,4,5]
    输出:[1,5,2,4,3]
    

    思路:

    这道题就是需要将链表首尾结点交替连接

    解法1:

    由于这是单向链表,所以没有前一个结点的指向,这个时候很自然的想到用数组,可以很方便的进行结点的选取

    代码:

    class Solution:
        def reorderList(self, head: ListNode) -> None:
            if not head: return
            nodes = []
            cur = head
            # 遍历所有节点将,结点放入nodes里进行缓存
            while cur:
                nodes.append(nodes)
                cur = cur.next
    
            i, j = 0, len(nodes) - 1
            # 头尾进行交替连接
            while i < j:
                nodes[i].next = nodes[j]
                i += 1
                # i+1之后如果和j相等,也就说明此时遍历已经完成,此时设置下一个结点为None,结束循环即可
                if i == j:
                  nodes[i].next = None 
                  break
                nodes[j].next = nodes[i]
                j -= 1
                    
    
    解法2:

    在这道题之前,我们已经写过怎么查找链表的中点,反转链表,以及合并链表的操作。此时可以想到,如果从终点到尾结点进行反转,然后两个结点交替相接,也可以满足题目要求。

    代码:

    class Solution:
            # 查询链表的中点,使用快慢指针
        def getMedian(self, head):
            slow = fast = head
            while fast and fast.next:
                fast = fast.next.next
                slow = slow.next
            return slow
            # 反转链表,先将下一个指针缓存,然后将当前指针指向前一个指针,分别将当前指针和前一个指针向后移动即可
        def reversed(self, head):
            prev, cur = None, head
            while cur:
                next = cur.next
                cur.next = prev
                prev = cur
                cur = next
            return prev
            # 合并两个链表,创建一个虚拟头结点,然后依次进行拼接,最后将未拼接完的拼接到链表后面即可
        def merge(self, l1, l2):
            cur = vHead = ListNode()
            while l1 and l2:
                cur.next = l1
                l1 = l1.next
                cur = cur.next
                cur.next = l2
                l2 = l2.next
                cur = cur.next
            cur.next = l1 or l2
            return vHead.next
    
    
        def reorderList(self, head: ListNode) -> None:
            if not head: return
            mid = self.getMedian(head)
            # 这里注意使用中点的下一个结点,目的是为了将前面的结点从中部进行切断,
            # 否则在合并的时候,头结点后面的也会进行合并,这样会导致拼接两次
            midRevered = self.reversed(mid.next)
            mid.next = None
            self.merge(head, midRevered)
    

    相关文章

      网友评论

        本文标题:leetcode链表之重排链表

        本文链接:https://www.haomeiwen.com/subject/gooujrtx.html