剑指Offer 06.从尾到头打印链表

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

 

示例 1:

输入:head = [1,3,2]
输出:[2,3,1]
 

限制:

0 <= 链表长度 <= 10000

 

个人思路:首先思考了一下链表是如何实现的。一开始一直将节点搞混,因为有一段时间没有写过代码了,特别是添加节点的之后链表的指针总会出现很多的错误。最后选择了通过画图来梳理了一下思路,最终回顾了一下单链表的创建。

代码如下:

 public ListNode createList(){

        Scanner scanner = new Scanner(System.in);
        ListNode firstNode = new ListNode();
        ListNode pauNode = new ListNode();
        pauNode = firstNode;
        while(true)
        {
            System.out.println("请输入添加节点的值,输入9999停止添加");
            int val = scanner.nextInt();
            if(val==999) break;
            else{
                ListNode listNode = new ListNode(val);
                pauNode.next =listNode;
                pauNode = listNode;
                pauNode.next = null;
            }
        }
        return firstNode;
    }


public class ListNode {
      int val;
      ListNode next;
      ListNode(int x) { val = x; }
      ListNode(){}
  }

 

大概的流程如下:首先有一个头节点,没有用来存储数据,就当作是这个链表的代表。节点最重要的不是数据val,而是下一个指针指向哪里。最开始的头节点的下一个指针肯定为真。然后第一个节点加进来的时候,需要将头节点的下一个指针指向这个刚加进来的节点,并把加进来的这个节点的下一个指针指向空。流程虽然很简单,但是要考虑一个问题,就是第二个节点加进来的时候我们只知道头节点的位置,并不知道第二个节点的位置,因为第二个节点是临时创建的,因此需要创建一个特殊的节点专门来存储当前节点的位置,就当作是这个链表的一个游标。这样的话链表的实现基本上就可以完成了。还有一个问题就是遍历链表的方法。可以通过while循环,也是通过一个临时的节点当作游标来移动,然后停止移动的条件就是当前节点的下一个指针为NULL。

 

在回顾完这个链表的内容后,就开始考虑题目的内容,就是想让链表的内容倒序输出。个人想法很简单就是遍历链表,然后将节点的值保存在数组里面。注意为了不产生多余的空间浪费,需要从后往前保存,这样就不用产生空间浪费。但是还存在着一个问题,就是事先并不知道链表的长度,因此打算使用LinkedList来作为中间的容器,这样可以就不用考虑链表长度。但我之前考虑使用LinkedList自带的转数组的函数来直接将Object[]类型的数组转换成Integer类型的数组,(为什么是Object类型呢,因为出现了类型擦除,导致JVM没有记住LinkedList的泛型的类型,所以依然是原始类型。)但是不能转换,这是为什么呢?因为虽然Object类型是所以类的父类,但是Object[]类型不是,如果想要转换的话需要通过循环对每一个的对象进行转换才行。所以这个函数暂时不考虑,因此还是选择创建一个新的数组。那么如何实现倒序呢?可以使用LinkedList自带的removeLast()就可以实现倒序的结果。

class Solution {
    public int[] reversePrint(ListNode head) {
        LinkedList<Integer> stack = new LinkedList<Integer>();
        while(head != null) {
            stack.addLast(head.val);
            head = head.next;
        }
        int[] res = new int[stack.size()];
        for(int i = 0; i < res.length; i++)
            res[i] = stack.removeLast();
    return res;
    }
}

 

第二种方法是之前想过的一个办法,使用LinkedList作为中间容器的原因就是因为不知道这个链表的长度,所以完全可以使用count,通过遍历链表来保存这个长度值。然后就可以创建数组,再通过一次遍历将节点的值输出即可。

class Solution {
    public int[] reversePrint(ListNode head) {
        ListNode tmp = head;
        int len = 0;
        while(tmp!=null){
            ++len;
            tmp = tmp.next;
        }

        int[] res = new int[len];
        tmp = head;
        int index = len-1;
        while(tmp!=null){
            res[index--] = tmp.val;
            tmp = tmp.next;
        }
        return res;
    }
}

 

posted @ 2021-11-02 10:20  夏天·烟火·我的尸体  阅读(37)  评论(0)    收藏  举报