参考自:《剑指Offer——名企面试官精讲典型编程题》
题目:从尾到头打印链表
输入一个链表的头结点,从尾到头反过来打印出每个结点的值。
主要思路:借助栈的后进先出特点,从头到尾添加数值到栈中,然后从栈中取出元素。另外也可以借助递归,递归实质上用到方法栈,但递归可能会导致方法栈溢出。
关键点:后进先出,递归
时间复杂度:O(链表长度)
public class ListFromTailToHead {
public static void main(String[] args) {
int[] data = {3, 4, 5, 7};
ListNode pHead = LinkedListData.generateDataByArray(data);
List<Integer> numbers = printListFromTailToHeadByStack(pHead);
System.out.println(numbers.toString());
}
/**
* 使用递归。链表太长的时候,容易导致方法栈溢出
*
* @param listNode the list node
* @return array list
*/
private static List<Integer> printListFromTailToHeadByRecursion(ListNode listNode, List<Integer> result) {
if (listNode != null) {
while (listNode.next != null) {
result = printListFromTailToHeadByRecursion(listNode.next, result);
}
//遍历到链表尾部时,再开始添加节点值
result.add(listNode.val);
}
return result;
}
/**
* 借助栈的特性,鲁棒性更好
*
* @param listNode the list node
* @return list
*/
private static List<Integer> printListFromTailToHeadByStack(ListNode listNode) {
Stack<Integer> stackRecords = new Stack<>();
while (listNode != null) {
stackRecords.push(listNode.val);
listNode = listNode.next;
}
List<Integer> result = new ArrayList<>();
while (!stackRecords.isEmpty()) {
result.add(stackRecords.pop());
}
return result;
}
}
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
class LinkedListData
{
/**
* 根据数组生成链表
*
* @param data the data
* @return list node
*/
public static ListNode generateDataByArray(int[] data) {
ListNode head = new ListNode(data[0]);
ListNode currentNode = head;
for (int i = 1; i < data.length; i++) {
ListNode next = new ListNode(data[i]);
currentNode.next = next;
currentNode = next;
}
return head;
}
}