剑指 Offer 24. 反转链表

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 24. 反转链表相关的知识,希望对你有一定的参考价值。

剑指 Offer 24. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

[外链图片转存中…(img-uMVTtihw-1630078203160)]

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

示例 2:

[外链图片转存中…(img-fEg773hU-1630078203162)]

示例 3:

输入:head = []
输出:[]

提示:

链表中节点的数目范围是 [0, 5000]

-5000 <= Node.val <= 5000

递归逆序

思路:

1、首先将1 -> 2 -> 3 ->4变成1 -> 4-> 3 -> 2(其中2 -> 3 ->4变成4-> 3 -> 2,采用递归方式实现)

2、再将head头节点1移到尾巴,作为尾结点,由于上一个尾结点2,是原先的head.next,此时将2的next指针指向头节点,即head.next.next = head,然后尾结点指向空,即head.next = None

[外链图片转存中…(img-eJ1LkIEX-1630078203163)]

3、特殊情况:头节点为空或者只有1个节点

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        #如果链表为空或者链表中只有一个元素
        if head is None or head.next is None:
            return head
        else:
            #反转后面的结点
            newhead = self.reverseList(head.next)
            #把当前遍历的结点加到后面结点逆序后链表的尾部
            head.next.next =head
            head.next = None
            return  newhead

算法性能分析:

由于递归法也只需要对链表进行 次遍历,因此,算法的时间复杂度也为 O(N) ,其中,N为链表的长度。

  • 递归法的主要优点是:思路比较直观,容易理解,而且也不需要保存前驱 结点的地址
  • 缺点是:算法实现的难度较大,此外,由于递归法需要不断地调用自己,需要 额外的压技与弹枝操作,因此, 与方法 2相比性能会有所降。

就地逆序

[外链图片转存中…(img-OttAYacM-1630078203164)]

移动:第1次指针操作,将当前节点指针cur.next值临时保存到nex,即nex = cur.next, 第2次指针操作,将当前的指针cur.next指向其前一个节点pre, 即cur.next = pre,这样就实现了对单个节点的操作。

操作节点的变量移动,pre结点后移:pre = cur ,cur指向下一个操作节点,即cur = nex,这样通过while循环即可实现对每个节点操作。

特殊情况:链表为空链表、链表为单节点,直接返回即可,无需逆序操作

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        #如果链表为空或者链表中只有一个元素
        if head is None or head.next is None:
            return head

        # 第一步:首结点变成逆转后尾结点
        cur = head # 链表首结点
        nex = cur.next # 原链表第二个结点
        cur.next = None # 断开原链表首结点与第二个结点链接
        # 第二步:依次逆转后续结点
        pre = cur # 记录前驱结点
        cur = nex # 后移一位
        while cur.next:
            nex = cur.next # 记录后继结点
            # 让当前结点指向前驱结点
            cur.next = pre # 逆转
            pre = cur  # 前驱结点后移
            cur = nex  # 链表后移,遍历
        # 第三步:头结点指向原链表尾结点,完成逆转
        cur.next = pre  # 此时的cur_node应该为:原链表尾结点,最后一次逆转
        head.next = cur # 头结点指向尾结点,完成逆转
        return  head  # 返回头结点
class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        #如果链表为空或者链表中只有一个元素
        if head is None or head.next is None:
            return head
        cur, pre = head, None
        while cur:
            nex = cur.next # 记录后继结点
            cur.next = pre # 逆转
            pre = cur  # 前驱结点后移
            cur = nex  # 链表后移,遍历
        return pre

参考

Krahets - 力扣(LeetCode) (leetcode-cn.com)

以上是关于剑指 Offer 24. 反转链表的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode(剑指 Offer)- 24. 反转链表

LeetCode(剑指 Offer)- 24. 反转链表

剑指Offer-代码的鲁棒性面试题24:反转链表

剑指 Offer 24. 反转链表 c++/java详细题解

剑指 Offer 24. 反转链表 c++/java详细题解

剑指 Offer 24. 反转链表