一、题目
题目链接:力扣
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。也就是说将链表的内容翻着放到数组中。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
限制:
0 <= 链表长度 <= 10000
二、题解
1、思路
欲将链表的内容翻着放到数组,可否先将链表内容正向放到数组,然后再将数组中的内容使用函数反转,应该是可以的,但是估计不是题目想让我们做的。
这道题目想考察什么知识点呢?数组的反转!当然题目的性质更像是字符串的反转!一般情况下使用双指针反转!此处使用一种更巧妙的方法:栈!利用栈后进先出的特性完成数组的反转!当然这种方法占用的空间复杂度高!当然,递归的本质利用的是栈。
本题解法:
- 🍌 递归法;
- 🍌 辅助栈;
- 🍌 双指针。
2、代码
// 递归法
class Solution {
public:
void reverse_list(ListNode* head, vector<int>& res)
{
// 截止条件不像《反转链表》那样需要if(head == NULL || head->next == NULL)
// 因为此处需要访问最后一个结点的值
if(head == NULL)return;
else reverse_list(head->next, res);
res.emplace_back(head->val);
}
vector<int> reversePrint(ListNode* head) {
vector<int> res;
if(head == NULL)return res;
reverse_list(head, res);
return res;
}
};
------------------------------------------------------------------------------
// 一个更好理解的解释
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
vector<int> res;
if(head == NULL)return res;
res = reversePrint(head->next);
res.emplace_back(head->val);
return res;
}
};
// 辅助栈
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
vector<int> res;
if(head == NULL)return res;
stack<int> stk;// 辅助栈
ListNode* p = head;
// 将链表内容复制到栈中
while(p != NULL)
{
stk.push(p->val);
p = p->next;
}
// 将栈的内容移动到数组
while(stk.empty() != true)
{
res.emplace_back(stk.top());
stk.pop();
}
return res;
}
};
// 双指针
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
vector<int> res;
if(head == NULL)return res;
ListNode* p = head;
// 将链表内容复制到数组
while(p != NULL)
{
res.emplace_back(p->val);
p = p->next;
}
// 将数组反转
// reverse(res.begin(), res.end());// 最好不要直接使用库函数
// 双指针反转(我自己起的名字)
int n = res.size();
for(int i = 0; i < n / 2; i++)
{
swap(res[i], res[n -1 - i]);
}
return res;
}
};
3、复杂度分析
使用数组返回,那么空间复杂度一定是O(n)。
🍌 递归:
时间复杂度:O(n);
空间复杂度:O(n)。
🍌 辅助栈:
时间复杂度:O(n);
空间复杂度:O(n)。
🍌 双指针:
时间复杂度:O(n);
空间复杂度:O(n)。
4、运行结果
递归法:
辅助栈:
双指针: