今日第二道题,链表、二叉树,虽然有的题目很简单,但是有时就是绕不出来,熟能生巧,见多了练多了就会了,我们一起加油哦~上题:
题目描述
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
方法一:中间桥梁——空间换时间
分析:需要将链表的值存到列表中,但是链表只能从头遍历,所以必须有个中间值作为桥梁,这里选列表,队列,栈都可以,考虑从尾到头,我就用栈作为中间值;
步骤:
1、先顺序遍历链表存入到栈中;
2、然后将栈中数据弹出,存入list中;
代码:
/**
* 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> array = new ArrayList<>();
Stack<Integer> stack=new Stack<>();
while(listNode != null){ //存进去
stack.push(listNode.val);
listNode=listNode.next;
}
while(!stack.isEmpty()){ //拿出来
array.add(stack.pop());
}
return array;
}
}
牛客运行通过
运行时间:19ms
运行内存:9428Kb
方法二:列表反转
分析:不使用额外的空间,只用列表,最后将列表进行反转;
代码:
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list= new ArrayList<>();
while(listNode!=null){ //从头到尾存进列表
list.add(listNode.val);
listNode=listNode.next;
}
int low=0;
int high=list.size()-1;
while(low<high){ //将列表反转;
int temp=list.get(low);
list.set(low,list.get(high));
list.set(high,temp);
low++;
high--;
}
return list;
}
}
牛客运行通过
运行时间:18ms
运行内存:9304Kb
方法三:利用ArrayList中add(index,element);
代码:
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> list= new ArrayList<>();
while(listNode!=null){
list.add(0,listNode.val); //一直将链表中的数插入到第一个
listNode=listNode.next;
}
return list;
}
}
牛客运行通过
运行时间:18ms
运行内存:9440Kb
方法四:递归
利用系统的“栈”,遍历到尾,在从尾返回存入列表。
代码
import java.util.ArrayList;
public class Solution {
ArrayList<Integer> list= new ArrayList<>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if(listNode!=null){
printListFromTailToHead(listNode.next);//不断递归,到链表尾
list.add(listNode.val); //递归结束,从尾开始存入列表。
}
return list;
}
}
牛客运行通过
运行时间:17ms
运行内存:9352Kb
四种方法其实都不需要初始判断,因为如果为空,下面代码不会执行。
方法一利用了额外的空间,利用空间换时间;
方法二只用一个列表存入,再进行反转;
方法三直接利用add(index,element)一步实现,省去了反转,奥利给~
方法四递归的思想,先递归到底,再返回存入。
递归虽然代码简单,但是如果链表很长,则递归太深,反而不好。这时用栈比较合适。
方法实在是太多了~~
只要思想不滑坡,方法总比困难多。
欢迎各位互相监督,互相交流哦~~