JZ6 从尾到头打印链表

 

链表是存储数据的一种方式,由于内存不是连续的,因此访问只能从表头访问表尾。本题需要从尾部到头打印链表,只能借助特殊的数据结构输出,但是访问顺序不会因此改变。

首先,可以借助递归是到达底层后才会往上回溯的特性来遍历链表。

复制代码
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).

最后,向vector插入元素时可以从右向左来遍历,这样也不需要开辟额外的空间,算法复杂度同样是O(1).

复制代码
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
       vector<int> res;
       if (head == nullptr) return res;

       int cnt = 0;//链表数据的长度
       ListNode* tmp = head;
       while(tmp != nullptr){
        cnt ++;
        tmp = tmp->next;
       }
       res.resize(cnt);//将res的大小设为链表长度
       int k = cnt - 1;
       while(head != nullptr){
        res[k -- ] = head->val;//从右向左存储数据
        head = head->next;
       }
       return res;
    }
};
复制代码

参考资料:《剑指offer》,帅地玩编程

 

O

 
posted @   luxiayuai  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示