栈
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public int[] reversePrint(ListNode head) {
ListNode p = head; // p指向头结点
int count = 0; // 计数器,用于统计链表长度
Stack<ListNode> stack = new Stack<>(); // 定义栈数据结构
ListNode curr = head; // 定义当前节点指针,初始指向头结点
while (curr != null) { // 遍历链表
stack.push(curr); // 将当前节点压入栈中
curr = curr.next; // 移动当前节点指针到下一个节点
count++; // 更新计数器
}
int[] res = new int[count]; // 创建结果数组,长度为计数器的值
int i = 0;
while (!stack.isEmpty()) { // 遍历栈
res[i] = stack.pop().val; // 将栈顶节点出栈,添加到结果数组中
i++; // 更新数组下标
}
return res; // 返回结果数组
}
}
纯循环
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public int[] reversePrint(ListNode head) {
ListNode p = head; // 定义指针p,初始指向头结点head
int count = 0; // 定义计数变量count,初始值为0
while (p != null) { // 遍历链表,统计链表的长度
count++; // 每遍历到一个节点,计数器count加1
p = p.next; // 指针p移动到下一个节点
}
int[] res = new int[count]; // 创建一个长度为count的整数数组res
p = head; // 将指针p重新指向头结点head
while (p != null) { // 遍历链表,将每个节点的值从后往前存储到数组中
res[--count] = p.val; // 将当前节点的值存储到数组res中,下标为count-1
p = p.next; // 指针p移动到下一个节点
}
return res; // 返回数组res
}
}
对比
这两段代码都实现了反向打印链表的功能,但是有以下几点不同:
- 空间复杂度:第一段代码使用了栈的数据结构,空间复杂度为O(n);第二段代码没有使用额外空间,空间复杂度为O(1)。
- 时间复杂度:两段代码的时间复杂度都是O(n),需要遍历整个链表。
- 实现难度:第一段代码使用栈更简单易实现,第二段代码需要反向遍历链表,实现难度稍微高一些。
- 扩展性:第一段代码使用栈更容易扩展到递归反转链表等其他功能。
总体来说,这两段代码都能完成要求,但就效率和实现难度而言,第二段代码稍微优于第一段代码。
不过第一段代码的可扩展性可能更好一些。