本文參考自《劍指offer》一書,代碼採用Java語言。html
更多:《劍指Offer》Java實現合集java
輸入一個鏈表的頭結點,從尾到頭反過來打印出每一個結點的值。結點定義以下:node
public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }
結點遍歷順序只能從頭至尾,可是輸出的順序卻爲從尾到頭,是典型的「後進先出」問題,這就要聯想到使用棧,從而也能夠聯想到使用遞歸。ide
測試用例函數
1.功能測試(單個結點鏈表,多個結點鏈表)post
2.特殊輸入測試(鏈表爲空)學習
import java.util.Stack; /** * * @Description 從尾到頭打印鏈表 * * @author yongh * @date 2018年9月10日 下午7:07:23 */ //題目:輸入一個鏈表的頭結點,從尾到頭反過來打印出每一個結點的值。 public class PrintListInReversedOrder { class ListNode{ int key; ListNode next; public ListNode(int key) { this.key=key; this.next=null; } } // 採用棧 public void printListReversingly_Iteratively(ListNode node) { Stack<ListNode> stack = new Stack<ListNode>(); while (node!= null) { stack.push(node); node=node.next; } while(!stack.empty()) { System.out.println(stack.pop().key); } } //採用遞歸 public void printListReversingly_Recursively(ListNode node) { if(node!=null) { printListReversingly_Recursively(node.next); System.out.println(node.key); }else return; } // ==================================測試代碼================================== /** * 鏈表爲空 */ public void test1() { ListNode aListNode = null; System.out.println("採用棧:"); printListReversingly_Iteratively(aListNode); System.out.println("採用遞歸:"); printListReversingly_Recursively(aListNode); } /** * 多個結點鏈表 */ public void test2() { ListNode ListNode1 = new ListNode(1); ListNode ListNode2 = new ListNode(2); ListNode ListNode3 = new ListNode(3); ListNode ListNode4 = new ListNode(4); ListNode ListNode5 = new ListNode(5); ListNode1.next=ListNode2; ListNode2.next=ListNode3; ListNode3.next=ListNode4; ListNode4.next=ListNode5; System.out.println("採用棧:"); printListReversingly_Iteratively(ListNode1); System.out.println("採用遞歸:"); printListReversingly_Recursively(ListNode1); } /** * 單個結點鏈表 */ public void test3() { ListNode ListNode1 = new ListNode(1); System.out.println("採用棧:"); printListReversingly_Iteratively(ListNode1); System.out.println("採用遞歸:"); printListReversingly_Recursively(ListNode1); } public static void main(String[] args) { PrintListInReversedOrder demo = new PrintListInReversedOrder(); System.out.println("test1:"); demo.test1(); System.out.println("test2:"); demo.test2(); System.out.println("test3:"); demo.test3(); } }
test1: 採用棧: 採用遞歸: test2: 採用棧: 5 4 3 2 1 採用遞歸: 5 4 3 2 1 test3: 採用棧: 1 採用遞歸: 1
遞歸部分代碼也能夠像下面這樣寫,注意體會不一樣的遞歸寫法:測試
// 採用遞歸 public void printListReversingly_Recursively(ListNode node) { // if(node!=null) { // printListReversingly_Recursively(node.next); // System.out.println(node.key); // }else // return; if (node != null) { if (node.next != null) { printListReversingly_Recursively(node.next); } System.out.println(node.key); } }
====================================================================ui
在牛客網中提交的代碼以下(參考自:grass_stars 的代碼):this
public class Solution { ArrayList<Integer> arrayList = new ArrayList<Integer>(); public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { if (listNode != null) { this.printListFromTailToHead(listNode.next); arrayList.add(listNode.val); } return arrayList; } }
上面代碼採用的遞歸,很是簡潔,很值得學習。
1.對於「後進先出」問題,要快速想到」棧「,也同時想到遞歸。
2.採用遞歸時,返回的函數值不必定要有賦值操做,只要實現了遍歷的做用就能夠了,上面牛客網的代碼能夠多多學習。