剑指offer——链表

本文详细介绍了链表的相关算法题目,包括从尾到头打印链表、反转链表和复制复杂链表。通过递归和哈希表等方法解决,提供了Python代码实现。

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

链表

offer6——从尾到头打印链表

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
在这里插入图片描述

解题思路

利用递归: 先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出。

算法流程

  1. 递推阶段: 每次传入 head.next ,以 head == NULL(即走过链表尾部节点)为递归终止条件,此时返回空列表 [] 。
  2. 回溯阶段: 利用 Python 语言特性,递归回溯时每次返回 当前 list + 当前节点值 [head.val] ,即可实现节点的倒序输出。

Python代码如下

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

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        #链表末端为空或时返回[]
        if not head: return []
        #递归回溯时每次返回 当前 list + 当前节点值 [head.val] ,即可实现节点的倒序输出。
        return self.reversePrint(head.next) + [head.val]

作者:jyd
来源:力扣(LeetCode)

offer24——反转链表

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
在这里插入图片描述
解题思路

使用递归法遍历链表,当越过尾节点后终止递归,在回溯时修改各节点的 next 引用指向。

算法流程
recur(cur, pre) 递归函数

  1. 终止条件:当 cur 为空,则返回尾节点 pre (即反转链表的头节点);
  2. 递归后继节点,记录返回值(即反转链表的头节点)为 res ;
  3. 修改当前节点 cur 引用指向前驱节点 pre ;
  4. 返回反转链表的头节点 res ;

reverseList(head) 函数

  1. 调用并返回 recur(head, null) 。传入 null 是因为反转链表后, head 节点指向 null ;

Python代码如下:

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        def recur(cur, pre):
            #终止条件,当 cur 为空,则返回尾节点 pre
            if not cur: return pre
            #递归后继节点直到最后节点,记录返回值(即反转链表的头节点)为 res 
            res = recur(cur.next,cur)
            #修改当前节点 cur 引用指向前驱节点 pre 
            cur.next = pre
            # 返回反转链表的头节点
            return res
        # 调用递归并返回
        return recur(head,None)

作者:jyd
来源:力扣(LeetCode)

offer35——复杂链表的复制

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
在这里插入图片描述在这里插入图片描述
解题思路

普通链表的节点定义如下:

# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None):
        self.val = int(x)
        self.next = next

本题链表的节点定义如下:

# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random

给定链表的头节点 head ,复制普通链表很简单,只需遍历链表,每轮建立新节点 + 构建前驱节点 pre 和当前节点 node 的引用指向即可。

本题链表的节点新增了 random 指针,指向链表中的 任意节点 或者 null。这个 random 指针意味着在复制过程中,除了构建前驱节点和当前节点的引用指向 pre.next ,还要构建前驱节点和其随机节点的引用指向 pre.random 。
本题难点:在复制链表的过程中构建新链表各节点的 random 引用指向。
在这里插入图片描述

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        cur = head
        dum = pre = Node(0)
        while cur:
            node = Node(cur.val) # 复制节点 cur
            pre.next = node      # 新链表的 前驱节点 -> 当前节点
            # pre.random = '???' # 新链表的 「 前驱节点 -> 当前节点 」 无法确定
            cur = cur.next       # 遍历下一节点
            pre = node           # 保存当前新节点
        return dum.next

算法流程
利用哈希表的查询特点,考虑构建原链表节点新链表对应节点 的键值对映射关系,再遍历构建新链表各节点的 next 和 random 引用指向即可。

1.若头节点 head 为空节点,直接返回 null ;
2.初始化: 哈希表 dic , 节点 cur 指向头节点;
3.复制链表:

  1. 建立新节点,并向 dic 添加键值对 (原 cur 节点, 新 cur 节点) ;
  2. cur 遍历至原链表下一节点;

4.构建新链表的引用指向:

  1. 构建新节点的 next 和 random 引用指向;
  2. cur 遍历至原链表下一节点;

5.返回值: 新链表的头节点 dic[cur] ;

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        #若头节点 head 为空节点,直接返回 null
        if not head: return 
        # 初始化哈希表,用于添加原节点cur:新节点cur
        dic = {}
        # 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射
        # 将 cur 指针重置为 head 头结点进行遍历
        cur = head
        while cur:
            dic[cur] = Node(cur.val)
            cur = cur.next
        cur = head
        #  构建新节点的 next 和 random 指向
        while cur:
            dic[cur].next = dic.get(cur.next)
            dic[cur].random = dic.get(cur.random)
            cur = cur.next

        #  返回新链表的头节点
        return dic[head]

作者:jyd
来源:力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值