描述
输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。
如输入{1,2,3}的链表如下图:
返回一个数组为[3,2,1]
0 <= 链表长度 <= 10000
解题思路
题目给定一个单链表,要求返回从尾到头的节点值组成的数组,这意味着我们需要从链表的尾部开始访问节点,并按此顺序收集节点的值,顺着这个思路我们首先可以想到用递归函数来解决这个问题,递归函数的调用栈本身就具有后进先出的特性,这与我们需要的从尾到头的顺序是非常吻合。
递归法
/**
* class ListNode(var `val`: Int) {
* var next: ListNode? = null
* }
*/
object Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param head ListNode类
* @return int整型一维数组
*/
fun printListFromTailToHead(head: ListNode?): IntArray {
val result = mutableListOf<Int>()
recursiveHelper(head, result)
return result.toIntArray()
}
private fun recursiveHelper(node: ListNode?, result: MutableList<Int>) {
if (node != null) {
recursiveHelper(node.next, result)
result.add(node.`val`)
}
}
}
代码中递归辅助方法 recursiveHelper
是一个私有方法,用于递归地遍历链表。当前节点node
和用于存储节点值的结果列表result
。如果当前节点不为空,方法首先递归调用自身,传入下一个节点node.next
和结果列表,这将导致链表的后续节点先被访问。在递归调用之后,当前节点的值node.val
被添加到结果列表
result中。由于递归调用是后进先出(LIFO)的,这确保了节点值被添加到列表的顺序是从链表尾部到头部。
private fun recursiveHelper(node: ListNode?, result: MutableList<Int>) {
if (node != null) {
recursiveHelper(node.next, result)
result.add(node.`val`)
}
}
但在题目中链表长度上限最高为10000,对于递归法来说在链表较长时可能会面临栈溢出的问题。除了递归函数外,栈的后进先出的特性也同时适合这道题,因此我们不妨考虑选择使用栈数据结构来模拟递归调用的过程。栈的后进先出特性可以帮助我们实现从尾到头的顺序,同时避免了递归调用过深的问题。
使用栈
/**
* class ListNode(var `val`: Int) {
* var next: ListNode? = null
* }
*/
object Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param head ListNode类
* @return int整型一维数组
*/
fun printListFromTailToHead(head: ListNode?): IntArray {
val stack = mutableListOf<Int>()
var currentNode = head
while (currentNode != null) {
stack.add(currentNode.`val`)
currentNode = currentNode.next
}
return stack.reversed().toIntArray()
}
}
初始化一个变量currentNode
为head
,表示链表的当前节点。使用while
循环遍历链表,直到currentNode
为null
,即链表的末尾。在每次循环中,将当前节点的值currentNode.val
添加到栈中。将currentNode
更新为下一个节点,即currentNode.next
。
使用栈数据结构来模拟递归过程。我们从头到尾遍历链表,将每个节点的值压入栈中,然后再弹出栈中的所有元素,得到的顺序就是从尾到头的顺序。