记录写题思考过程,方便日后系统复习
一、题目介绍
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
输入:head = [1,3,2]
输出:[2,3,1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、解题思路
参考链接:
作者:tangweiqun
链接: 点击.
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
1、输入一个链表头结点和(输入一个链表)这两句话是等价的。
即题目要求的是:
输入:1 -> 3 -> 2 -> 8
输出:[8, 2, 3, 1]
在链表中的每个节点使用类ListNode来表示,代码如下:
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
2、这道题目的输入是一个链表,输出的是一个数组。
链表具有的特点:
① 事先链表的长度是不知道的,也就是说事先你不知道链表中存在多少节点
② 链表只能从头节点开始往后遍历,而不能从非头结点往前遍历
数组具有的特点:
① 数组初始化的时候就必须指定长度
② 不仅可以从数组的第一元素往后遍历访问数组,而且也可以从最后一个元素往前遍历数组
所以,我们要返回一个数组,首先需要计算出这个数组的长度,实际上数组的长度就等于链表的节点的个数,那么问题就变成了求链表的节点个数了,这样求解:
先初始化一个整形变量 length
从链表的头节点往后遍历,每遇到一个节点,那么 length 就自加 1,一直到链表的空节点为止
得到了数组的长度后,我们就可以初始化一个结果数组,然后再次从链表的头节点开始往后遍历,每遇到一个节点,那么就将节点的值放到数组的后端 (这里利用了数组可以从最后一个元素往前访问的特点)
代码如下(示例):
class Solution {
//时间复杂度:O(n)
//空间复杂度:O(n)
public int[] reversePrint(ListNode head) {
//如果这是一个空链表,直接构造一个新的数组返回
//head是头指针
if(head == null){
return new int[]{};
}
//1、计算链表的长度
int length = 0;
//需要再声明一个指针,循环遍历使用
ListNode curr = head;
while(curr != null){
length++;
curr = curr.next;
}
//2、初始化存放结果的数组
int[] res = new int[length];
//3、按照反方向将链表节点值存放在数组中
int i = length - 1;
curr = head;
while(curr != null){
res[i] = curr.val;
i--;
curr = curr.next;
}
return res;
}
}
3、辅助栈
这道题需要解决的问题本质上就是将链表倒序了,而由于链表只能从头节点往后遍历,所以我们可以借助栈来完成链表的倒序排列过程。
栈的特点是:后进先出,即最后压入的元素最先弹出。
我们可以从链表的头节点开始,依次压入栈中,然后再从栈中依次取出的节点的顺序就是原链表的倒序了
class Solution{
public int[] reversePrint(ListNode head){
if(head == null){
return new int[]{};
}
//1、先将链表从头至尾的节点依次添加到栈中
//定义栈时,必须加泛型,否则声明的栈 中的数据类型为Object
Stack<ListNode> stack = new Stack<>();
ListNode curr = head;
while(curr != null){
stack.push(curr);
curr = curr.next;
}
//2、依次从栈中取出节点,然后添加到数组中
int[] res = new int[stack.size()];
int i = 0;
//判断栈是否为空
while(!stack.isEmpty()){
res[i] = stack.pop().val;
i++;
}
return res;
}
}