一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
题目:给定一个链表的头节点,要求用数组返回链表的倒序。
例如:
输入:head = [1,3,2]
输出:[2,3,1]
解题思路
因为栈具有先进后出的特性,因此根据本题要求,我们可以将链表元素从前往后入栈,之后依次出栈保存至结果数组中即可,代码如下:
public static int[] reversePrint(ListNode head){
Stack<Integer> stack = new Stack<>();
while(head!=null){
stack.push(head.val);
head = head.next;
}
int size = stack.size();
int[] result = new int[size];
for(int i=0;i<size;i++){
result[i] = stack.pop();
}
return result;
}
时间复杂度和 空间复杂度都是。
上面的方法用到了栈,因为只需要将结果保存至数组中,我们是否可以直接遍历链表将结果倒序存入结果数组,这样栈的空间复杂度就不需要了,代码如下:
public int[] reversePrint(ListNode head){
int len = 0;
ListNode temp = head;
while(temp!=null){
len++;
temp = temp.next;
}
int[] result = new int[len];
for(int i=len-1;i>=0;i--){
result[i] = head.val;
head = head.next;
}
return result;
}
这样如果不算输出数组的空间复杂度,最终空间复杂度就是。
本题算是做出来了,但是想象一下,本题是否还是链表逆序的变体,在此处复习一下链表倒序:
链表倒序可使用递归和非递归两种方式解决,下面一一展示:
-
非递归:非递归方式很简单,实现定义一个空节点,之后使用头插法的方式将节点插入空节点之后即可,最终的逆序就是空节点.next。用此思路解决本题代码如下:
public int[] reversePrint(ListNode head){ if(head == null) return new int[0]; ArrayList<Integer> list = new ArrayList<>(); ListNode headPoint = new ListNode(-1); while(head!=null){ ListNode tempNode = head.next; head.next = headPoint.next; headPoint.next = head; head = tempNode; } while(headPoint.next!=null){ list.add(headPoint.next.val); headPoint = headPoint.next; } return list.stream().mapToInt(Integer::valueOf).toArray(); }最终耗时
3ms,和上面差距有点大。 -
递归:递归的方式很巧妙,我们需要注意当遍历到最后一个节点时,我们就需要将链表进行返回,而不能继续遍历下去,具体代码如下:
public int[] reversePrint(ListNode head){ if(head == null) return new int[0]; ArrayList<Integer> list = new ArrayList<>(); head = reverseList(head); while(head!=null){ list.add(head.val); head = head.next; } return list.stream().mapToInt(Integer::valueOf).toArray(); } public static ListNode reverseList(ListNode head){ if(head == null || head.next == null) return head; ListNode p = reverseList(head.next); head.next.next = head; head.next = null; return p; }最终耗时也是
3ms。但这两种思路是必须掌握的!