面试题6:从尾到头打印链表
题目描述:
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
题解1:递归。递归终止条件:head = null,意味着遍历到了链表的尾部,同时也意味着,可以回溯递归的值。
第一次递归:recur(1)->recur(3)
第二次递归:recur(3)->recur(2)
第三次递归:recur(2)->null;
此时进行回溯:将值添加到数组中
第一次回溯:add(2)
第二次回溯:add(3)
第三次回溯:add(1)
最后打印数组即从尾到头遍历了链表,因为是将链表的值存储数组中,所以并未改变原链表的状态。
时间复杂度O(N):遍历链表,递归N次
空间复杂度O(N):系统递归调用需要O(N)的空间
//递归 ArrayList<Integer> temp = new ArrayList<>(); public int[] reversePrint(ListNode head) { recur(head); int[] res = new int[temp.size()]; for (int i = 0;i<res.length;i++){ res[i] = temp.get(i); } return res; } /* 一直递归到null结束,结束后的值是null的前一个值,也就是数组的最后一个值。 */ public void recur(ListNode head){ if (head == null){ return; } recur(head.next); temp.add(head.val); }
题解二:利用栈
从尾到头打印完美符合栈的特点:先进后出
将元素依次入栈再依次出栈即可,Java中可以使用LinkedList实现栈。
入栈:addLast将元素添加到列表末尾。
出栈:removeLast删除并返回列表尾最后一个元素(不能使用getLast,因为getLast会一直返回表尾最后一个,返回的都是同一个元素)
时间复杂度O(N):入栈和出栈使用O(N)时间
空间复杂度O(N):额外栈和数组共使用O(N)空间
//辅助栈方法 public int[] reversePrint(ListNode head) { LinkedList<Integer> stack = new LinkedList<>(); while (head != null) { stack.addLast(head.val); head = head.next; } int[] res = new int[stack.size()]; for (int i =0 ;i<res.length;i++){ res[i] = stack.removeLast(); } return res; }
解法三:
遍历一遍链表,记录链表中元素的数量。
创建一个数组,以链表中的元素数量为大小,同时从元素数量-1索引处开始循环,向数组中从后往前添加链表元素的值。
时间复杂度:遍历链表和遍历数组添加元素各占用O(N),时间复杂度为O(N)
空间复杂度:O(1),不需要额外空间
public class Solution3 { public int[] reversePrint(ListNode head) { //先遍历一遍链表记录元素的数量 int count = 0; ListNode temp = head; while(temp != null){ count++; temp = temp.next; } int[] arr = new int[count]; temp = head; //从后往前 添加到数组中 for (int i = count - 1; i >=0 ; i--){ arr[i] = temp.val; temp = temp.next; } return arr; } }
学习的博客多用于在笔记中,防止笔记过于臃肿,所以将样例及运行结果放在博客中,后以超链接的形式记录在笔记中,所以有些博文过于单薄。如果有小伙伴遇到问题欢迎评论,看到就会回复,学渣一枚,加油努力。