Description
Difficulty: Simple
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 :
1 2
| 输入:head = [1,3,2] 输出:[2,3,1]
|
Solution - 1: Stack
思路: 栈的特点是后进先出,即最后压入栈的元素最先弹出。考虑到栈的这一特点,使用栈将链表元素顺序倒置。从链表的头节点开始,依次将每个节点压入栈内,然后依次弹出栈内的元素并存储到数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public int[] reversePrint(ListNode head) { Stack<ListNode> stack = new Stack<ListNode>(); ListNode temp = head; while (temp != null) { stack.push(temp); temp = temp.next; } int size = stack.size(); int[] print = new int[size]; for (int i = 0; i < size; i++) { print[i] = stack.pop().val; } return print; } }
|
同理也可以用LinkedList:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Solution { public int[] reversePrint(ListNode head) { LinkedList<Integer> stack = new LinkedList<Integer>(); 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; } }
|
时间复杂度:O(n) 正向遍历一遍链表,然后从栈弹出全部节点,等于又反向遍历一遍链表。
空间复杂度:O(n) 额外使用一个栈存储链表中的每个节点。
Solution - 2: 递归
思路: 先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { ArrayList<Integer> tmp = new ArrayList<Integer>(); public int[] reversePrint(ListNode head) { recur(head); int[] res = new int[tmp.size()]; for(int i = 0; i < res.length; i++) res[i] = tmp.get(i); return res; } void recur(ListNode head) { if(head == null) return; recur(head.next); tmp.add(head.val); } }
|
时间复杂度 O(n): 遍历链表,递归 N 次。
空间复杂度 O(n): 系统递归需要使用 O(n) 的栈空间。
Solution - 3:
思路: 不用饯也不用递归,只要知道链表的长度即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Solution { public static int[] reversePrint(ListNode head) { ListNode node = head; int count = 0; while (node != null) { ++count; node = node.next; } int[] nums = new int[count]; node = head; for (int i = count - 1; i >= 0; --i) { nums[i] = node.val; node = node.next; } return nums; } }
|
时间复杂度 O(n):同样是要扫描两趟
空间复杂度 O(1): 不需要额外分配空间
Summary
- 写这题的时候发现java的各种数据结构和方法名称都忘的差不多了。。
- 递归本质上就是一个栈,先进后出。
总之希望自己能坚持下去,每周记录分享几道有趣的题和解法。也欢迎大家留言讨论补充(●’◡’●)