链表是存储数据的一种方式,由于内存不是连续的,因此访问只能从表头访问表尾。本题需要从尾部到头打印链表,只能借助特殊的数据结构输出,但是访问顺序不会因此改变。
首先,可以借助递归是到达底层后才会往上回溯的特性来遍历链表。
class Solution { public: void recursion(ListNode* head, vector<int> & res)//注意引用的传参方式 { if(head == nullptr) return;//递归的终止条件 recursion(head->next, res);//访问顺序是从头到尾 res.push_back(head->val);//再填充到数组就是逆序 } vector<int> printListFromTailToHead(ListNode* head) { vector<int> res; recursion(head, res); return res; } };
另外,还有借助栈的后入先出的特性,也能够逆序输出链表。
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; } };
两者的时间复杂度都是O(n),空间复杂度都是O(n),因为递归栈也是占用空间的。需要注意,当链表非常长时,会导致函数调用的层级很深,从而有可能导致函数调用栈溢出。用栈基于循环实现的代码的鲁棒性要好一些。
下面是第三种解法:反转链表
vector<int> printListFromTailToHead(ListNode* head) { ListNode *pre, *tmp, *cur; pre = nullptr; cur = head; while(cur){ tmp = cur -> next; cur->next = pre; pre = cur; cur = tmp; } vector<int> res; while(pre){ res.push_back(pre->val); pre = pre->next; } return res; }
这个要是理解的话最好去牛客网的题解里找一下那个动图,只要理解了pre,cur和tmp三个指针的含义,其实就非常好理解了。
这个优化了空间,为O(1).
O
标签:pre,head,cur,res,链表,vector,从尾,JZ6 From: https://www.cnblogs.com/luxiayuai/p/17245900.html