反转链表系列题总结

96 阅读1分钟

反转链表系列题总结

206. 反转链表

—— 最基本的反转链表

迭代

func reverseList(head *ListNode) *ListNode {
    //迭代
    var prev *ListNode
    cur := head
    for cur != nil {
        next := cur.Next
        cur.Next = prev
        prev = cur
        cur = next
    }
    return prev
}

递归

func reverseList(head *ListNode) *ListNode {
    if head == nil || head.Next == nil {
        return head
    }
    newHead := reverseList(head.Next)
    head.Next.Next = head
    head.Next = nil
    return newHead
}

反转链表前k个节点

迭代

func reverseK(head *ListNode, k int) *ListNode {//反转链表前k个节点
    if k <= 1 {
        return head
    }
    var prev *ListNode
    cur := head
    for i := 0; i < k && cur != nil; i++ {
        next := cur.Next
        cur.Next = prev
        prev = cur
        cur = next
    } 
    head.Next = cur
    return prev
}

递归

var successor *ListNode //递归法reverseK需要用到的变量,记录第k+1个节点

func reverseK(head *ListNode, k int) *ListNode {//反转链表前k个节点
    if k == 0 {
        return head
    }
    if k == 1 {//给第k+1个节点successor赋值
        successor = head.Next
        return head
    }
    newHead := reverseK(head.Next, k - 1);
    head.Next.Next = head
    head.Next = successor
    return newHead
}

92. 反转链表 II

—— 反转链表从left~right的部分

用到 反转链表前k个节点 作为子函数

迭代

若left==1,则直接返回reverseK(head, right - left + 1)

若left!=1,cur移动到第left个节点(prev指向第left-1个节点),perv.Next = reverseK(cur, right - left + 1),最后返回head

func reverseBetween(head *ListNode, left int, right int) *ListNode {
    if left == 1 {
        return reverseK(head, right - left + 1)
    }
    cur := head
    var prev *ListNode = nil
    for i := 1; i < left && cur != nil; i++ {
        prev = cur
        cur = cur.Next
    }
    if cur == nil {
        return head
    }
    prev.Next = reverseK(cur, right - left + 1)
    return head
}

递归

若left==1,则直接返回reverseK(head, right - left + 1)

若left!=1,head.Next = reverseBetween(head.Next, left - 1, right - 1), 最后return head

func reverseBetween(head *ListNode, left int, right int) *ListNode {
    if left == 1 {
        return reverseK(head, right - left + 1)
    }
    head.Next = reverseBetween(head.Next, left - 1, right - 1)
    return head
}

25. K 个一组翻转链表

仍然用到 反转链表前k个节点 作为子函数

迭代

func reverseKGroup(head *ListNode, k int) *ListNode {
    //首先要判断是否有>=k个节点,否则直接返回原来的head不做任何操作
    if head == nil {
        return head
    }
    cur := head
    for i := 1; cur != nil && i < k; i++ {
        cur = cur.Next
    }
    if cur == nil {//没有k个节点了,不反转了直接返回原来的head
        return head
    }
    
    //确定有>=k个节点后,开始迭代调用。(此时cur指向第k个节点)
    cur.Next = reverseKGroup(cur.Next, k) //迭代 k个一组反转第k+1个节点开头的链表
    newHead := reverseK(head, k) //反转前k个
    return newHead
}