题目描述
输入一个链表,从尾到头打印链表每个节点的值。
思路(用的是Java)
1、先遍历链表,然后利用栈结构“后进先出”的特点,将链表依次存入栈,然后弹栈输出,可以用一个ArrayList存储,最后返回一个ArrayList,便是从尾到头的链表。
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.*;
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
Stack<Integer> stack = new Stack<Integer>();
while(listNode!=null){
stack.push(listNode.val); //入栈
listNode=listNode.next;
}
ArrayList<Integer> list = new ArrayList<Integer>();
while(!stack.empty())
list.add(stack.pop()); //弹栈并且添加到数组中
return list;
}
}
2、网上大神的解法,非常厉害。递归到链表最后一个节点,然后每次递归回到最外圈的时候都会将节点添加到数组中,最后直接返回数组就可以。代码巨简洁!
//链接:https://www.nowcoder.com/questionTerminal/d0267f7f55b3412ba93bd35cfa8e8035
//来源:牛客网
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;
}
}
照例,笔记马克一下Java相关知识点或者数据结构
1、实现List接口的类
集合框架核心接口的基本结构树类:Collection(还有一个大类是Map)
(1)ArrayList类
实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的,不是多线程安全。)
每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。
- ArrayList常用方法
- 增加元素到链表中
boolean add(Element e)
增加指定元素到链表尾部.
void add(int index, Element e)
增加指定元素到链表指定位置.
- 从链表中删除元素
void clear()
从链表中删除所有元素.
E remove(int index)
删除链表中指定位置的元素.
protected void removeRange(int start, int end)
删除链表中从某一个位置开始到某一个位置结束的元素。
- 获取链表中的元素
E get(int index)
获取链表中指定位置处的元素.
Object[] toArray()
获取一个数组,数组中所有元素是链表中的元素.(即将链表转换为一个数组)
- 修改某个元素
E set(int index, E element)
将链表中指定位置上的元素替换成新元素。
- 搜索元素
boolean contains(Object o)
如果链表包含指定元素,返回true.
int indexOf(Object o)
返回元素在链表中第一次出现的位置,如果返回-1,表示链表中没有这个元素。
int lastIndexOf(Object o)
返回元素在链表中最后一次出现的位置,如果返回-1,表示链表中没有这个元素。
- 检查链表是否为空
boolean isEmpty()
返回true表示链表中没有任何元素.
- 获取链表大小
int size()
返回链表长度(链表包含元素的个数).
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
(3)Vector
实现动态数组。与新 collection 实现不同,Vector 是同步的。
- Vector常用方法
- void addElement(Object obj):在集合的最后增加一个元素
- void add(int index,Object element):在指定位置增加一个元素
- int capacity():返回当前容量
- int size():返回集合的元素个数
- void insertElementAt(Object obj,int index):在指定位置插入元素
- Object elementAt(int index):返回指定位置的元素
ArrayList,Vector主要区别为以下几点:
(1):Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比;
(2):ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
(3):Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。
2、写一个链表结构(题目提示已给出)
public class ListNode
{
int val;
ListNode next;
public ListNode(int x){
val=x;
}
}
3、Java自带的栈类Stack(java.util)
Stack
类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的 search 方法。
- empty 测试堆栈是否为空。
public boolean empty()
返回:当且仅当堆栈中不含任何项时返回 true
;否则返回 false
。
- push
public E push(E item)
参数:item
- 压入堆栈的项。
返回:item
参数。
- pop 移除堆栈顶部的对象,并作为此函数的值返回该对象。
public E pop()
-
-
返回:
堆栈顶部的对象(
Vector
对象中的最后一项)。
抛出:
EmptyStackException
- 如果堆栈为空 -