输入一个链表的头节点,从尾到头反过来打印输出每个节点的值。链表节点定义如下:
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
首先会想到的方法是改变链表的方向,然后就可以从头到尾输出。
不过通常打印是一个只读操作,我们不希望打印时修改内容。
当我们遍历链表的时候 顺序是从头到尾,可输出的顺序是要求从尾到头,很容易想到,我们可以用栈(先进后出,后进先出)来实现这种顺序。
public int[] reversePrint(ListNode node) {
Stack<Integer> stack = new Stack<>();
while (node != null) {
stack.add(node.val);
node = node.next;
}
int size = stack.size();
int[] res = new int[size];
for (int i = 0; i < size; i++) {
res[i] = stack.pop();
}
return res;
}
既然想到用栈实现,递归本质上就是一个栈结构。于是我们也可以用递归来实现。要实现反过来输出链表,我们每访问到一个节点的时候,先递归输出它后面的节点,再输出该节点自身,这样链表的输出结果就反过来了。
public int[] reversePrint(ListNode node) {
ArrayList<Integer> list = new ArrayList<>();
recursive(list, node);
int size = list.size();
int[] res = new int[size];
for (int i = 0; i < size; i++) {
res[i] = list.get(i);
}
return res;
}
private void recursive(ArrayList<Integer> list, ListNode node) {
if (node != null) {
if (node.next != null)
recursive(list, node.next);
list.add(node.val);
}
}
递归方法和stack方法都需要用到辅助的数据结构来记录链表中的每个值,然后遍历存放到数组中。因此空间复杂度为O(n),我们可以进一步降低空间复杂度,第一次遍历链表获取链表的长度,第二次遍历直接用数组从尾部向前获取node的value。
public int[] reversePrint(ListNode node) {
// 第一次遍历获取链表长度len
ListNode curNode = node;
int len = 0;
while (curNode != null) {
len++;
curNode = curNode.next;
}
int[] res = new int[len];
// 第二次遍历向res赋值
curNode = node;
while (curNode != null) {
res[--len] = curNode.val;
curNode = curNode.next;
}
return res;
}