方法一
暴力法,时间复杂度较高
public int[] reversePrint(ListNode head) {
ListNode cur = head;
List<Integer> list = new ArrayList<>();
while (cur != null) {
list.add(cur.val);
cur = cur.next;
}
Collections.reverse(list);
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
res[i] = list.get(i);
}
return res;
}
方法二
递归法
解题思路:利用递归: 先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出。
Java 算法流程:
递推阶段: 每次传入 head.next ,以 head == null(即走过链表尾部节点)为递归终止条件,此时直接返回。
回溯阶段: 层层回溯时,将当前节点值加入列表,即tmp.add(head.val)。
最终,将列表 tmp 转化为数组 res ,并返回即可。
复杂度分析:
时间复杂度 O(N)O(N): 遍历链表,递归 NN 次。
空间复杂度 O(N)O(N): 系统递归需要使用 O(N)O(N) 的栈空间。
// 递归法
// 时间复杂度 O(N)O(N): 遍历链表,递归 NN 次。
// 空间复杂度 O(N)O(N): 系统递归需要使用 O(N)O(N) 的栈空间。
public int[] reversePrint(ListNode head) {
recur(head);
int[] res = new int[list.size()];
for (int i = 0; i < res.length; i++) {
res[i] = list.get(i);
}
return res;
}
List<Integer> list = new ArrayList<>();
public void recur(ListNode node) {
if (node == null) {
return;
}
recur(node.next); // 先递归到最后节点
list.add(node.val); // 回溯,加入此节点值
}
方法三
辅助栈法:这种 先入后出 的需求可以借助 栈 来实现。
复杂度分析:
时间复杂度 O(N)O(N): 入栈和出栈共使用 O(N)O(N) 时间。
空间复杂度 O(N)O(N): 辅助栈 stack 和数组 res 共使用 O(N)O(N) 的额外空间。
// 利用栈的特性
// 时间复杂度 O(N)O(N): 入栈和出栈共使用 O(N)O(N) 时间。
// 空间复杂度 O(N)O(N): 辅助栈 stack 和数组 res 共使用 O(N)O(N) 的额外空间。
public int[] reversePrint(ListNode head) {
Stack<Integer> stack = new Stack<Integer>();
while (head != null) {
stack.push(head.val);
head = head.next;
}
int[] res = new int[stack.size()];
for (int i = 0; i < res.length; i++) {
res[i] = stack.pop();
}
return res;
}