题目链接
剑指 Offer 06. 从尾到头打印链表 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
输入链表的头节点,按照从尾到头的顺序打印每个节点的值(用数组返回)
示例
输入:head = [1,3,2]
输出:[2,3,1]
解题思路一
由于链表只能从前向后遍历访问每个节点,题目要求倒序输出节点的值。这类涉及到先入后出,顺序翻转的需求,可以考虑借助栈来实现。具体思路为从前到后遍历链表,将各节点的值写入栈中,完成后再依次将元素弹出。
在Python中,栈可以利用list来实现,其中利用append()函数实现入栈,利用pop(index = -1)函数实现出栈(pop函数用于移除列表中的一个元素,默认index为-1,即移除最后一个元素,并且返回该元素的值),将出栈的元素存储到待返回的数组中。当然Python中可以直接将列表逆序输出。
由于遍历一遍链表的时间复杂度为O(N),逆序时间复杂度为O(N),因此整体时间复杂度为O(N)。 由于需要额外线性空间,空间复杂度为O(N)。
代码实现一
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reversePrint(self, head):
"""
:type head: ListNode
:rtype: List[int]
"""
x = head
return_list = []
while(x):
return_list.append(x.val)
x = x.next
return_list.reverse() #原地反转
return return_list
#也可以直接返回return_list[::-1]
逆序可以通过list[::-1]或list.reverse()原地倒序实现。
解题思路二
可以利用递归+回溯实现。利用递归走到链表末尾,停止递归,回溯时依次将节点值append到待返回的列表中,由于链表末尾的节点值会先加入链表,因此能够实现逆序输出。
由于需要遍历一遍数组,时间复杂度为O(N),另外需要额外的栈空间实现递归,空间复杂度为O(N)。
在写递归函数时要明确三点:
(1)递归函数的功能
(2)递归函数的终止条件
(3)递归过程中参数的缩小形式以及如何根据下一层递归结果得到当前层递归结果。
对于当前这个问题,递归函数recursive(node)返回的是以node为头节点的链表的逆序输出结果;递归函数的终止条件为node为空节点,此时递归函数返回空列表[];
每层递归调用下一层递归函数时,输入参数设置为node.next,即得到以node.next为头节点的链表的逆序输出列表。我们将当前节点node的值追加到该列表末尾,就能够得到以node为头节点的链表的逆序输出结果。
比如链表1->2->3->4,recursive(2)返回列表[4,3,2],将节点1追加到该列表末尾,返回的是以节点1为头节点的链表逆序输出结果,即[4,3,2,1]。
代码实现二
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def reversePrint(self, head):
"""
:type head: ListNode
:rtype: List[int]
"""
if not head: #递归终止条件,如果head为空,那么就返回空列表
return []
return self.reversePrint(head.next) + [head.val] #同样是扩充列表,+运算符生成一个新对象,extend会原地修改原对象
参考
面试题06. 从尾到头打印链表(递归法、辅助栈法,清晰图解) - 从尾到头打印链表 - 力扣(LeetCode) (leetcode-cn.com)