从尾到头打印链表——剑指Offer
题目描述
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
解题思路
使用递归
如传入1->2->3,则需返回3,2,1。根据递归的压栈弹栈,可通过递归函数实现从尾到头将链表中的值add到ArrayList中。
/** * public class ListNode { * int val; * ListNode next = null; * * ListNode(int val) { * this.val = val; * } * } * */ import java.util.ArrayList; public class Solution { ArrayList<Integer> ret=new ArrayList<>(); public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { //如果当前节点不为空 if(listNode!=null){ //递归传入当前节点的next printListFromTailToHead(listNode.next); //当递归结束后以递归出栈顺序将值add到ArrayList。起到逆序的作用。 ret.add(listNode.val); } return ret; } }
使用头插法
使用头插法可以得到一个逆序的链表。
头结点和第一个节点的区别:
- 头结点是在头插法中使用的一个额外节点,这个节点不存储值;
- 第一个节点就是链表的第一个真正存储值的节点。
import java.util.ArrayList; public class Solution { ArrayList<Integer> ret=new ArrayList<>(); public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { //头插法构建逆序链表 ListNode head=new ListNode(-1); while(listNode != null){ //记录当前节点的next ListNode memo = listNode.next; //将当前节点的next指向head的next(从第二个节点开始就实现了逆序,指向了前一个节点) listNode.next = head.next; //head的next指向当前节点 head.next = listNode; //listNode赋值为next,进入下一次循环 listNode = memo; } //head的next开始为有效值 head=head.next; //依次将链表值add到ArrayList中 while(head != null){ ret.add(head.val); head=head.next; } return ret; } }
使用栈
栈具有后进先出的特点,在遍历链表时将值按顺序放入栈中,最后出栈的顺序即为逆序。
import java.util.ArrayList; import java.util.Stack; public ArrayList<Integer> printListFromTailToHead3(ListNode listNode) { //创建一个栈 Stack<Integer> stack = new Stack<>(); //依次将链表的值压栈 while (listNode != null) { stack.add(listNode.val); listNode = listNode.next; } ArrayList<Integer> ret = new ArrayList<>(); //依次弹栈 while (!stack.isEmpty()) { ret.add(stack.pop()); } return ret; }