15.反转链表-剑指offer-Python2.7

本文详细介绍了剑指Offer第15题“反转链表”的两种解决方案:非递归和递归方法。非递归方式通过三个指针操作完成链表的反转,递归方法则是从链表尾部开始翻转,直至头部。文章提供了Python代码实现,适合初学者理解链表反转的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指offer第15题 牛客网在线编程链接 https://www.nowcoder.com/activity/oj
反转链表

题目描述
输入一个链表,反转链表后,输出新链表的表头。

思路1
首先,用指针p指向第一个元素节点来保存第一个元素节点的位置。用一个指针q指向一个指针域为空的节点,这个节点用来做为链表反转后的最后一个节点。
用指针pr保存指针p原来指向的下一个节点,然后让指针p从指向原始的节点变为指向q(起初为空节点),指针p和指针q分别向前移动一步(q,p = p,pr)。依次类推,直至指针p指向原链表最后一个空节点。
当p指向链表的空节点时,,q指向倒数第一个节点,即链表反转后的首节点,此时链表倒置已完成。

Python2.7编写

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
        
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        #用指针p指向第一个元素节点来保存第一个元素节点的位置。
        #用一个指针q指向一个指针域为空的节点。
        p = pHead
        q = None 
        #当链表为空时,直接返回None
        if not pHead:
            return 
        
        while p != None:
            pr = p.next #用指针pr保存指针p原来指向的下一个节点
            p.next = q #让指针p从指向原始的节点变为指向q
            q,p = p,pr #指针p和指针q分别向前移动一步
        return q

推广
这里是没有头指针的链表,对于有头指针的链表,处理方式稍有不同。
假设当前创建好的链表如下:
在这里插入图片描述首先让头节点与第一个元素节点断开,但是要注意在断开之前需要用p指针指向第一个元素节点来保存第一个元素节点的位置,然后再断开。在这里有一个指针q指向一个指针域为空的节点,这个节点用来做为链表反转后的最后一个节点。
在这里插入图片描述让第二个元素节点的指针从指向第三个元素节点变为指向第一个元素节点,依次类推,直至指针p指向原链表最后一个元素。
在这里插入图片描述在这里插入图片描述在这里插入图片描述p指针指向NULL时,让原头节点的指针域指向原来最后一个元素节点。此时链表倒置已完成。
在这里插入图片描述

# -*- coding:utf-8 -*-
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        p = pHead.next #指针p保存第一个元素节点的位置
        q = None #用来作为链表反转后的尾节点
        pHead.next = None #头节点与第一个元素断开
        #直到p到达原链表尾结点,终止while循环
        while p: 
            pr = p.next #用指针pr保存指针p原来指向的下一个节点
            p.next = q #让指针p从指向原始的节点变为指向q
            q,p = p,pr #指针p和指针q分别向前移动一步
        pHead.next = q
        return pHead

注:代码未经测试,逻辑是正确的。

思路2 递归
我们再来看看递归实现链表翻转的实现,前面非递归方式是从前面数1开始往后依次处理,而递归方式则恰恰相反,它先循环找到最后面指向的数5,然后从5开始处理依次翻转整个链表。
首先指针H迭代到底如下图所示,并且设置一个新的指针作为翻转后的链表的头。由于整个链表翻转之后的头就是最后一个数,所以整个过程NewH指针一直指向存放5的地址空间。
在这里插入图片描述
然后H指针逐层返回的时候依次做下图的处理,将H指向的地址赋值给H->next->next指针,并且一定要记得让H->next =NULL,也就是断开现在指针的链接,否则新的链表形成了环,下一层H->next->next赋值的时候会覆盖后续的值。

继续返回操作:
在这里插入图片描述
上图第一次如果没有将存放4空间的next指针赋值指向NULL,第二次H->next->next=H,就会将存放5的地址空间覆盖为3,这样链表一切都大乱了。接着逐层返回下去,直到对存放1的地址空间处理。
在这里插入图片描述
返回到头:

在这里插入图片描述

# -*- coding:utf-8 -*-
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
        
def ReverseListRec(self, pHead):
        if not pHead or not pHead.next: #链表为空直接返回,而pHead.next为空是递归基
            return pHead
        else:
            pReversedHead = self.ReverseList(pHead.next) #一直循环到链尾
            pHead.next.next = pHead  #翻转链表的指向
            pHead.next = None  #记得赋值NULL,防止链表错乱
            return pReversedHead #新链表头永远指向的是原链表的链尾

写在后面
推广和思路2部分为复制的内容,图文来源分别为
推广:https://blog.youkuaiyun.com/blioo/article/details/62050967
思路2:https://blog.youkuaiyun.com/fx677588/article/details/72357389
https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target Offer/反转链表.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值