反转链表,设置两个指针变量,分别 指向前一个节点 和 当前节点,然后改变指针的next指向。有以下两种方式,两种思路一样,一种迭代的方式,一种是递归的方式。时间复杂度都是O(N)的,空间为O(1)

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:

    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        cur, pre = pHead, None
        while cur:
            cur.next, pre, cur = pre, cur, cur.next # 如果是Java/c++需要引入临时变量
        return pre
    """
    def ReverseList(self, pHead):
        def recur(pre, cur):
            # 递归边界
            if not cur:return pre
            # 递归
            res = recur(cur, cur.next)
            # 回溯
            cur.next = pre
            return res
        return recur(None, pHead)
    """ 

本题的引申题目:给定区间的链表反转。
对于增加难度的反转链表,给定了左右边界,只对内部的子链进行反转。
思路:在本题的基础上,增加子链前后节点的标记;找到子链的左右位置,切断子链在整条链表中的左右连接,然后用本题的方式对子链进行反转;然后用子链前后的标记指针将左中右三部分穿起来。

class Solution:
    def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
        def reverse_linked_list(head: ListNode):  # 也可以使用递归反转一个链表
            pre, cur = None, head
            while cur:
                # 将pre->cur转为pre<-cur,然后pre指向cur,cur指向下一个
                cur.next, pre, cur = pre, cur, cur.next

        # 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
        dummy_node = ListNode(-1)
        dummy_node.next = head
        pre = dummy_node
        # 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
        for _ in range(left - 1):
            pre = pre.next
        # 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
        right_node = pre
        for _ in range(right - left + 1):
            right_node = right_node.next
        # 第 3 步:切断出一个子链表(截取链表)
        left_node = pre.next
        curr = right_node.next

        # 注意:切断链接
        pre.next = None
        right_node.next = None

        # 第 4 步:同第 206 题,反转链表的子区间
        reverse_linked_list(left_node)
        # 第 5 步:接回到原来的链表中
        pre.next = right_node
        left_node.next = curr
        return dummy_node.next