本文參考自《劍指offer》一書,代碼采用Java語言。
題目
輸入一個鏈表的頭結點,從尾到頭反過來打印出每個結點的值。結點定義如下:
public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }
思路
結點遍歷順序只能從頭到尾,但是輸出的順序卻為從尾到頭,是典型的“后進先出”問題,這就要聯想到使用棧,從而也可以聯想到使用遞歸。
測試用例
1.功能測試(單個結點鏈表,多個結點鏈表)
2.特殊輸入測試(鏈表為空)
完整Java代碼
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);
}
}
====================================================================
在牛客網中提交的代碼如下(參考自:grass_stars 的代碼):
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.采用遞歸時,返回的函數值不一定要有賦值操作,只要實現了遍歷的作用就可以了,上面牛客網的代碼可以多多學習。
