剑指offer | 面试题6:从尾到头打印链表

转载本文章请标明作者和出处
本文出自《Darwin的程序空间》
本文题目和部分解题思路来源自《剑指offer》第二版

在这里插入图片描述

开始行动,你已经成功一半了,献给正在奋斗的我们

题目

输入一个链表(单向链表)的头节点,从尾到头反过来打印出每个节点的值。

链表的节点定义如下:

public class ListNode {

    // 链表值
    public int val;
    // 下一节点的引用
    public ListNode next;

    // 构造函数
    public ListNode(int x) {
        val = x;
    }
}

解题分析

首先,如果这是一道面试题,我们需要和面试官确认是否可以改变原有的数据结构;这道题是遍历,打印通常是一个只读的操作,这里假定是不能够更改原有数据结构的条件。

首先我们分析,链表作为一个链状结构,需要打印,我们肯定需要从头到尾遍历一遍,才能拿到所有的元素并打印出来,所以这道题的时间复杂度锁定在了O(n)。

遍历是从前往后遍历,然后题目要求我们的是从后往前打印,这就涉及到了一个问题,先遍历的要后输出,说到这,这道题求解肯定要用到一种先进后出的数据结构了,就是栈结构。

栈结构是怎么完成,从后往前打印的效果的呢?
假设我们有链表1-2-3-4,我们先把四个节点依次压入栈中,等到链表所有的元素都进入到了栈中,我们依次弹栈并打印,这样就可以完成逆序打印的效果了。
剑指offer | 面试题6:从尾到头打印链表_第1张图片
具体实现,我们可以借用Java中帮我定义好的Stack类,来实现压栈和弹栈的操作。
但其实我们的虚拟机栈本身就是个栈,我们可以使用回溯的方法,让方法压栈和出栈,从而达到我们需要的效果。
(逻辑就是,我们定义一个打印的方法,但是只有当前这个元素的next元素不为null的情况下我们才打印这个元素的值,如果next元素不为null就以这个元素的next元素为入参继续调用这个方法)

剑指offer | 面试题6:从尾到头打印链表_第2张图片

代码(JAVA实现)

ps:这里笔者使用的jdk为1.8版本

public class PrintListFromTailToHead {

    public static void main(String[] args) {
        printListFromTail(LinkedListUtil.getLinkedList(new int[]{1, 2, 3, 4}));
    }

    public static void printListFromTail(ListNode head) {
        if (Objects.isNull(head)) {
            return;
        }
        printListFromTail(head.next);
        System.out.println(head.val);
    }

}

LinkedListUtil为笔者自己定义方便做链表题目的工具类,代码如下:


/**
 * @program: algorithm_code
 * @description: 链表工具类
 * @author: YangHang
 * @create: 2019-09-01 21:56
 **/

public class LinkedListUtil {

    /**
     * 获取一个链表
     */
    public static ListNode getLinkedList(int[] numbers) {

        if (numbers == null || numbers.length == 0) {
            return null;
        }

        ListNode first = new ListNode(numbers[0]);
        ListNode intermediateVariables = first;

        for (int i = 1; i < numbers.length; i++) {
            ListNode temp = new ListNode(numbers[i]);
            intermediateVariables.next = temp;
            intermediateVariables = intermediateVariables.next;
        }

        return first;
    }

    /**
     * 打印一个链表
     */
    public static void printLinkedList(ListNode first) {
        ListNode intermediateVariables = first;

        while (!Objects.isNull(intermediateVariables)) {

            System.out.printf("%s-> ", intermediateVariables.val);
            intermediateVariables = intermediateVariables.next;
        }
        System.out.println();

    }

    // 测试工具类
    public static void main(String[] args) {
        printLinkedList(getLinkedList(new int[]{1, 2, 3, 4, 5, 6, 7}));
    }
}
喜欢的朋友可以加我的个人微信,我们一起进步

你可能感兴趣的:(剑指offer,算法)