剑指Offer-链表-面试题6:从尾到头打印链表


输入一个链表的头结点,从尾到头反过来打印每个节点的值。链表节点的定义如下(略)。

思路

倒序输出显然想到栈结构,结合链表与栈。

解法

解法1思路

对于输入一个链表的头结点,一直在纠结,不知道怎么处理。
(1)首先是调用LinkedList问题,即便调用了,也不能new Node(), Node是一个静态内部私有类,会报 Node is not an enclosing class。即要创建内部类的实例,需要有外部类的实例才行,或者是将内部类设置为静态的,添加 static 关键字
(2)用自己写的API的,不能new Node()与上面同样的错误;但是在面试中不可能提前写好,笔试也不能调用整个写好的API。
(3)所以需要临时写一个适用场景的基本链表数据结构,数据结构是什么名字不重要,重要的是其有什么成员变量的属性。何为链表呢?链表就是由一排结点连接而成的,每个结点有两个属性:一为这个结点存储的值,一为这个结点指向的下一个结点。 实际应用场景中,我们只需要知道头结点就知道了整个链表。
(4)况且题目中给出了结点的构造,也就是暗示我们自己造轮子。
(5)另外,在面试时需要询问面试官能否改变链表的原始结构。
(6)最后解法1使用链表和栈结构。
[Q1] 栈结构为什么可以直接调用呢 -_-

解法1代码

public class ReverseOutLinkedList {

    public static void main(String[] args) {
        /**
         * 链表节点
         */
        class Node{
            int data;
            Node next;

            public Node(int data) {
                this.data = data;
            }
            Node(){}
        }
        //给出头结点
        Node headNode = new Node(1);
        //链表赋值
        Node node2 = new Node(3);
        Node node3 = new Node(4);
        Node node4 = new Node(2);
        Node node5 = new Node(5);
        headNode.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;

        Stack<Integer> stack = new Stack<>();

        /**
         * 1.用头结点可以找到这个链表  {1,3,4,2,5}
         * 2.怎么知道长度,不知道长度怎么遍历——最后一个 指针为空值的时候遍历停止呗
         */
        while (headNode.next!=null){
            stack.push(headNode.data);
            headNode=headNode.next;
        }
        stack.push(headNode.data);
        System.out.println("倒序输出:");
        while (stack.size()!=0){
            System.out.print(stack.pop() );
        }
    }
}

解法2思路

解法一的改进写法
(1)将Node节点类变成外部类。
(2)将while (headNode.data!=null)改成while (headNode!=null)直接改变了后续的值取尽问题。

解法2代码

/**
 * 链表节点
 */
class Node{
    int data;
    Node next;

    public Node(int data) {
        this.data = data;
    }
    Node(){}
}

/**
 * 面试题6:从尾到头打印链表
 *      输入一个链表的头结点,倒序输出每个节点的值
 *
 * @author Heroin X
 * @date 2019/12/2 20:26
 */
public class ReverseOutLinkedList {

    public static void main(String[] args) {
        //给出头结点
        Node headNode = new Node(1);
        //链表赋值
        Node node2 = new Node(3);
        Node node3 = new Node(4);
        Node node4 = new Node(2);
        Node node5 = new Node(5);
        headNode.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;

        new ReverseOutLinkedList().test1(headNode);
        //new ReverseOutLinkedList().test2(headNode);
    }

    public void test1(Node headNode){

        Stack<Integer> stack = new Stack<>();
        /**
         * 1.用头结点可以找到这个链表  {1,3,4,2,5}
         * 2.怎么知道长度,不知道长度怎么遍历——最后一个 指针为空值的时候遍历停止呗
         */
        while (headNode!=null){
            stack.push(headNode.data);
            headNode=headNode.next;
        }
        //stack.push(headNode.data);
        System.out.println("倒序输出:");
        while (stack.size()!=0){
            System.out.print(stack.pop() );
        }
    }
 }

解法3思路-递归

递归写法,
(1)while (headNode.next!=null)if(headNode.next!=null),造成死循环问题——似乎是while循环不能递归回上一层级。
(2)test2(headNode.next);headNode=headNode.next; test2(headNode);的不同 ?第2种写法打印出的结果是5 5 2 4 3
(3)鲁棒性缺点的说法

解法3代码

    public void test2(Node headNode){
        //1 3 4 2 5
        if (headNode!=null){
            //while (headNode.next!=null){
            if (headNode.next!=null){
                //headNode=headNode.next;
                test2(headNode.next);
            }
            System.out.print(headNode.data+" ");
           // headNode.next=null;
        }
    }
}

解法3代码2

大佬的超级简洁写法

//链接:https://www.nowcoder.com/questionTerminal/d0267f7f55b3412ba93bd35cfa8e8035?f=discussion

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;
    }
}  

解法4-OJ

nowcoder的AC
提交时间:2020-01-02, 语言:Java ,运行时间: 21 ms ,占用内存:9392K, 状态:答案正确
在OJ平台上可以发现一些问题点:
(1)Stack与ArrayList都是可以直接引用的,并且包是import java.util.ArrayList、Stack
(2)边界条件,注意空输入!
(3)while(stack.size()>0)中stack的方法掌握熟练度(不知道有size()方法),其次是对于开始写的是while(stack==null)一直没起作用?listNode == null vs stack==null的区别?
listNode 在此处只是一个结点,而stack是一个容器,不是一个量级的。容器一般会用size来衡量;而中间的具体某一个元素或者对象才会使用null来进行判别。

/**
*    public class ListNode {
*        int val;
*        ListNode next = null;
*
*        ListNode(int val) {
*            this.val = val;
*        }
*    }
*
*/
import java.util.ArrayList;
import java.util.Stack;
 
public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {

        ArrayList<Integer> list = new ArrayList<>();
        //error1
        Stack<Integer> stack =new Stack<>();
         
        //边界条件一定要考虑!error3
        if(listNode == null){
            return list;
        }
         
        while(listNode!=null){
            stack.push(listNode.val);
            listNode=listNode.next;
             
        }
         
        //java.util.EmptyStackException
        while(stack.size()>0){
            //error2
            list.add(stack.pop());
        }
         
        return list;
    }
}

解法5-真正的递归-200911

class Solution {
    List<Integer> list = new ArrayList<>();
    public int[] reversePrint(ListNode head) {
        re(head);
        int[] arr = new int[list.size()];
        for(int i = 0; i < list.size(); i++){
            arr[i] = list.get(i);
        }
        return arr;
    }

    public void re(ListNode node){
        if(node==null){
            return ;
        }
        re(node.next);
        list.add(node.val);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值