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

问题

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
限制:
0 <= 链表长度 <= 10000

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
问题分析

两种解法:
1、利用“栈”来进行辅助存储
因为栈具有 先进后出 的特点,正好可以通过栈:
从前往后遍历链表,并将遍历到的节点(!=null),压入栈stack中。在遍历链表结束以后,再将栈中的元素一个个出栈,arr[i++] = stack.pop().val; 实现逆序的将链表中各个节点的值,存入到数组中
2、递归解决
1)实际上,该方法使用递归解决的话,就必须先要明确:因为递归方法是在便利的过程中进行操作的,所以一开始不能定义为数组来存储 链表逆序的val顺序(因为链表的长度是未知的)。所以,可以采取 集合 来先存储(因为集合 可以扩容)。
2)确定递归的终止条件:
head == null
对应:遍历到链表的末尾。实际上,这个条件也包含了 链表本身为空,即,最初的 head == null 的情况。
3)递归过程中进行的操作:
function(head.next,list);//递归调用下一个节点
list.add(head.val);//在递归返回的过程中,将链表中的每个节点对应的val值,放到list中去

代码实现

1、利用“栈”来进行辅助存储

class Solution {
    public int[] reversePrint(ListNode head) {
        //因为题目中没有说明是否可以改变原链表的顺序,所以借助栈来实现
        ListNode cur = head;//定义一个用于遍历链表的指针cur,并指向链表的“头节点”
        int count = 0;//用于记录链表长度的变量
        //定义一个栈用于存储链表中的节点
        Stack<ListNode> stack = new Stack();
        //链表中,用于遍历的指针cur指向的节点不为空的时候,循环就需要进行
        while(cur != null){
            stack.push(cur);
            count ++ ;
            cur = cur.next;//这个是实现遍历链表的语句
        }
        int[] arr = new int[count];
        //当栈非空时,要将栈中的元素出栈,并且将刚出栈的元素的val值,赋值给arr[]中的相应元素
        // ListNode temp ;//暂存出栈的节点
        int i=0;//控制数组下标的变量
        while(!stack.empty()){
            arr[i++] = stack.pop().val;
            // temp = stack.pop();
            // arr[i++] = temp.val;
        }
        return arr;

    }
}

2、使用递归

class Solution {
    public int[] reversePrint(ListNode head) {
        //使用一个ArrayList来逆序存储各个节点val(利用ArrayList的长度可变的原理,因为在刚开始的时候,是不知道转化后的数组的长度的)。并在最终,通过list.get(index),来读取集合中的元素,赋值给数组,并返回,即可
        //因为是引用类型,所以,实际上是:由递归调用而创建的所有的栈空间,使用同一个list
        ArrayList<Integer> list = new ArrayList<Integer>();//类型推断
       //尝试一下,使用递归的解法
       function(head, list);
       //将list转化为对应的数组,并返回
       int[] arr = new int[list.size()];
       for(int i=0;i<arr.length;i++){
           arr[i] = list.get(i);//利用的是集合的“查”的方法
       }
       
       return arr;
    }

    //注意:这里使用递归来解题的划分依据:
    //递归的终止条件是遍历到的节点本身为空(head == null),此时,因为该节点本身不存在,所以不需要做list.add()操作
    //----不能将head.next == null,作为递归的终止条件。这是因为:此时的话,递归终止条件就没有办法包含:head节点本身为空(链表为空的情况)
    //但是,在非递归终点的条件下,需要做list.add()的操作
    public  void function(ListNode head,List list){
        //是递归的终点,也包含了第一个节点就是递归终点的情况
        if(head == null){
           //到达最后一个节点
           return;
       }
       function(head.next,list);
       //在递归返回的过程中,将链表中的每个节点对应的val值,放到list中去
       list.add(head.val);
       return;
    }
}

加油,坚持每天刷题。
并且,在刷题的过程中,坚持练习 递归 的思想!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值