[剑指-Offer] 6. 从尾到头打印链表(链表逆置、递归、鲁棒性、多方法)

1. 题目来源

链接:LeetCode 从尾到头打印链表
来源:LeetCode——《剑指-Offer》专项

2. 题目说明

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

示例 1:

输入:head = [1,3,2]
输出:[2,3,1]

限制:

  • 0 <= 链表长度 <= 10000

3. 题目解析

3.1 方法一:逆置链表、顺序遍历输出

在面试手撕编程题时,若需要修改原来的数据输入结构时,需要首先询问面试官是否允许修改。这取决于面试官的要求。切记!

在面试手撕编程题时,若需要修改原来的数据输入结构时,需要首先询问面试官是否允许修改。这取决于面试官的要求。切记!
在面试手撕编程题时,若需要修改原来的数据输入结构时,需要首先询问面试官是否允许修改。这取决于面试官的要求。切记!

在此只是简单复习一下单链表的原地逆置,即三指针原地逆置法。

参见代码如下:

// 执行用时 :8 ms, 在所有 C++ 提交中击败了67.78%的用户
// 内存消耗 :9.7 MB, 在所有 C++ 提交中击败了100.00%的用户

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        vector<int> vt;
        if (head == nullptr)
            return vt;
        head = ReverseList(head);
        for (ListNode* p = head; p != nullptr; p = p->next)
            vt.push_back(p->val);
        return vt;
    }

    ListNode* ReverseList(ListNode* pHead) {
        if (pHead->next == nullptr || pHead==nullptr)
            return pHead;
        ListNode* pre = NULL;
        ListNode* cur = pHead;
        ListNode* next = NULL;
        while (cur != NULL) {
            next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};

3.2 方法二:辅助栈空间

“后进先出”,很自然能想到stack的使用。

参见代码如下:

// 执行用时 :8 ms, 在所有 C++ 提交中击败了67.78%的用户
// 内存消耗 :9.9 MB, 在所有 C++ 提交中击败了100.00%的用户

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        vector<int> vt;
        stack<int> st;
        if (head == nullptr)
            return vt;
        for (ListNode* p = head; p != nullptr; p = p->next)
            st.push(p->val);
        while (!st.empty()) {
            vt.push_back(st.top());
            st.pop();
        }
        return vt;
    }
};

3.3 方法三:递归法

简单的递归思想:递归本质上就是一个栈结构,每次访问到一个节点时,先递归输出它后面的节点,再输出该节点自身,递归即可反向输出。

递归方法虽然简单,但是当链表长度较长时,导致函数调用深度过深引发栈溢出。显然栈基于循环实现的代码的鲁棒性要好一点。

// 执行用时 :112 ms, 在所有 C++ 提交中击败了5.06%的用户
// 内存消耗 :265.9 MB, 在所有 C++ 提交中击败了100.00%的用户
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> vt;
    vector<int> reversePrint(ListNode* head) {
        if (head == nullptr)
            return vt;
        reversePrint(head->next);
        vt.push_back(head->val);
        return vt;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值