题目的主要信息:
- 输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值
- 返回值保存在vector的数组中
方法一:递归
具体做法:
我们都知道递归到底层后才会往上,因此我们可以递归遍历链表,将填充数组放到递归函数后面,就可以实现遍历到链表最后再逐渐往前将值填到数组中。
class Solution {
public:
void recursion(ListNode* head, vector<int>& res){ //递归函数
if(head != NULL){
recursion(head->next, res); //先往链表深处遍历
res.push_back(head->val); //再填充到数组就是逆序
}
}
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
recursion(head, res); //递归打印
return res;
}
};复杂度分析:
- 时间复杂度:
,递归遍历一次链表
- 空间复杂度:
,递归栈的空间为链表长度
方法二:栈
具体做法:
递归的思想也可以用栈实现,递归本质上就是用栈实现的。我们可以顺序遍历链表,将链表的值push到栈中,然后再依次弹出栈中的元素,加入到数组中。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
stack<int> s;
while(head != NULL){ //正序输出链表到栈中
s.push(head->val);
head = head->next;
}
while(!s.empty()){ //输出栈中元素到数组中
res.push_back(s.top());
s.pop();
}
return res;
}
};复杂度分析:
- 时间复杂度:
,遍历链表是一个
,弹空一个栈需要
- 空间复杂度:
,栈空间最大长度是链表的长度
方法三:反转数组
具体做法:
题目只需要最后输出的数组是链表的逆序,那我们可以顺序遍历链表,依次输入到链表中,最后用reverse函数将数组反转即可。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
while(head != NULL){ //正序输出到数组中
res.push_back(head->val);
head = head->next;
}
reverse(res.begin(), res.end()); //函数反转数组
return res;
}
};复杂度分析:
- 时间复杂度:
,一次遍历,reverse函数复杂度也是
- 空间复杂度:
,res属于返回函数必要空间,不属于额外空间
方法四:逆序填充数组
具体做法:
这种方法的思想是输入到数组中的值按照下标的逆序来输入,这样一来我们就要先确定vector数组有多大,可以先遍历一次链表得到链表长度也即是数组长度。然后从数组最后的下标开始按顺序填充链表中的值即可。
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
int n = 0;
ListNode* p = head; //遍历的指针
while(p != NULL){ //统计链表长度
n++;
p = p->next;
}
vector<int> res(n, 0); //限定返回数组的大小
p = head;
while(p != NULL){ //遍历链表
res[n - 1] = p->val; //数组上逆序记录
p = p->next; //链表往后
n--; //下标往前
}
return res;
}
};复杂度分析:
- 时间复杂度:
,统计长度一次遍历,填充数组一次遍历
- 空间复杂度:
,res属于返回函数必要空间,无额外空间使用

京公网安备 11010502036488号