剑指Offer-6-从尾到头打印链表
第一种思路是用栈
- 遍历链表,将每一个节点值压入栈中
- 弹栈,逆向输出整个链表
class Solution {
public:
vector reversePrint(ListNode* head) {
vector result;
// 将链表的每一个节点值都压入栈中
stack st;
// 其实我不确定下面的写法是不是会有问题
for(ListNode* i = head;i!=nullptr;i+1){
st.push(i->val);
}
// 弹出栈中元素并放入数组中
while(!st.empty()){
result.push_back(st.top());
st.pop();
}
return result;
}
};
但是两次遍历很明显时间效率不高甚至超时(事实上除了空都超时了)
第二种思路则是,利用递归
class Solution {
public:
vector reversePrint(ListNode* head) {
vector result;
// 每次访问一个节点时,先输出它的下一个节点
next(head,result);
return result;
}
void next(ListNode* head,vector &result){
if(head!=nullptr){
if(head->next!=nullptr){
next(head->next,result);
}
result.push_back(head->val);
}
}
};
但总感觉应该还有更好的解法
以及…优化,当然如果能解决返回值的问题的话就不用单独再写一个方法了
看到评论里有一个这样的写法
public:
vector reversePrint(ListNode* head) {
if(!head)
return {};
vector a=reversePrint(head->next);
a.push_back(head->val);
return a;
}
};
看起来非常简洁,但其实不太好——在于每一次的递归都会创建一个局部变量数组,如果链表长了,递归层级多了,很难说不会超内存
执行用时没有减少,而内存消耗增加了
这里还有一种”预分配+逆向指针“的解法
class Solution {
public:
vector reversePrint(ListNode* head) {
ListNode* node = head;
size_t count = 0;
// 这个循环是在计数链表长度
while (node != nullptr) {
++count;
node = node->next;
}
vector nums(count);// 预分配数组长度
node = head;
// rbegin()方法是获取反向迭代器
for(auto i = nums.rbegin(); i != nums.rend(); ++i){
*i=node->val;
node=node->next;
}
return nums;
}
};
确实效果更好了