143.重排链表

95 阅读2分钟

题目描述

给定一个单链表 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, 5 * 104]
  • 1 <= node.val <= 1000

思路

思路1 链表法

将整个链表分成前后两个部分,将后面部分逆置后,和前面部分重新链接在一起,核心算法包括

  1. 使用快慢指针寻找中间节点前驱的算法
  2. 反转链表的算法
  3. 重新链接两个链表的算法

代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reorderList(head *ListNode)  {
    var midNode, head2 *ListNode
    midNode = findMidNode(head)
    head2 = midNode.Next
    midNode.Next = nil

    head2 = reverse(head2)
    var next1, next2 *ListNode
    for head != nil && head2 != nil {
        next1, next2 = head.Next, head2.Next
        
        head.Next = head2
        head2.Next = next1

        head = next1
        head2 = next2   
    }
}

func reverse(head *ListNode) *ListNode {
    var pre *ListNode
    for head != nil {
        next := head.Next
        head.Next = pre
        pre= head
        head = next
    }
    return pre
}

func findMidNode(node *ListNode) *ListNode {
    var slow, fast *ListNode
    slow, fast = node, node
    for fast != nil && fast.Next != nil {
        slow = slow.Next
        fast = fast.Next.Next
    }
    return slow
}

图示

image.png

思路2

思考:本题思路还是比较清晰的,但是链表不支持随机访问,只能顺序访问。所以我们想着能不能将其转换为支持顺序访问的形式,于是我们就有了:将链表形式转换为线性表形式的想法。

使用一个辅助数组,将链表转换为数组,通过下标直接访问完成指针的重新指向,以完成链表的重排。

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reorderList(head *ListNode)  {
    var nodes []*ListNode
    for head != nil {
        nodes = append(nodes, head)
        head = head.Next
    }
    var i, j int
    for i, j = 0, len(nodes)-1; i < j; i, j = i+1, j-1 {
        nodes[i].Next = nodes[j]
        if i+1 == j { // 不能指向自己
            break
        }
        nodes[j].Next = nodes[i+1]
    }
    nodes[j].Next = nil
}

图示

奇数长度

image.png

偶数长度(需要特殊判断)

image.png