剑指 Offer 06. 从尾到头打印链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
限制: 0 <= 链表长度 <= 10000
本题主要是对链表的学习,我学习了三种方法来解决。
第一种方法就是遍历两遍链表,第一遍遍历获取链表长度,第二遍遍历是把链表中的元素倒序放到数组中。
class Solution {
public int[] reversePrint(ListNode head) {
ListNode currNode = head;
int len = 0;
while(currNode != null){
len ++;
currNode = currNode.next;
}
int[] res = new int[len];
currNode = head;
while(currNode != null){
res[len - 1] = currNode.val;
len --;
currNode = currNode.next;
}
return res;
}
}
第二种方法用到的是递归,回溯的概念,通过递归,然后回溯元素值写到动态数组中。
class Solution {
ArrayList<Integer> tmp = new ArrayList<Integer>();
public int[] reversePrint(ListNode head) {
//先获取链表长度,创建对应长度数组
//todo 回溯 递归
recur(head);
int[] result = new int[tmp.size()];
for(int i = 0;i<result.length;i++) {
result[i] = tmp.get(i);
}
return result;
}
void recur(ListNode head){
if(head == null)return;
recur(head.next); //递归head。next到null
tmp.add(head.val);//tmp依次从后往前回溯。
}
第三种方法就是用到了栈,因为栈的先进后出的特性,很适合倒序的输出。而对栈的使用,也是学会了两个方法,一个是直接用linkedlist,对其输入输出控制,第二个是用到Deque,用push和pop进行输入输出。
//使用linkedlist,输入输出为addlast和removelast。
class Solution {
public int[] reversePrint(ListNode head) {
LinkedList<Integer> list = new LinkedList<Integer>();
while(head != null){
list.addLast(head.val);
head = head.next;
}
int[] res = new int[list.size()];
for(int i = 0;i<res.length;i++){
res[i] = list.removeLast();
}
return res;
}
}
//Deque 双端队列 是一种具有队列和栈的性质的数据结构,用push和pop
class Solution {
public int[] reversePrint(ListNode head) {
Deque<Integer> list = new LinkedList<Integer>();
while(head != null){
list.push(head.val);
head = head.next;
}
int[] res = new int[list.size()];
for(int i = 0;i<res.length;i++){
res[i] = list.pop();
}
return res;
}
}
对于链表的理解,其实一开始看了很久,都还是没有理解了,然后去交流,才忽然间明白了,之前对head的理解都是错的,我把他当做了一个节点来看,就感觉很奇怪,后来才明白,这是类似指针的东西,之前也很少编链表的题目,所以从头开始很是艰难,一遇到困难就不想搞,幸好这次克服了!
链表的概念挺多的,虽然题目是写出来了,但是还有好多没去看,顺便来巩固今天的内容...
下一节是树,今天也是看了一点,也自己去把二叉树的三个遍历都学了一遍并且码了出来,(递归函数真的有点绕,但是真的可以让问题简单化)。