剑指offer:06从尾到头打印链表(不修改链表结构)

通常打印时一个只读操作,我们不希望打印时修改内容。假设面试官也要求这个题目不能改变链表的结构。 

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

 示例1:

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

输出:[2,3,1]

限制:

0 <= 链表长度 <= 10000

方法一:reverse()反转

1.c++中的STL库中的begin(),end()用法

2.vector用法

3.reverse()用法

代码语言:cpp

/**
 * 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> res;
        while (head){    //循环压入
            res.push_back(head->val);
            head = head->next;
        }
        reverse(res.begin(),res.end());    //反转
        return res;
    }
};

24 / 24 个通过测试用例

状态:通过

执行用时: 4 ms

内存消耗: 8.5 MB

  • 时间复杂度 O(N)
  • 空间复杂度 O(1)

方法二: 利用堆栈

思路:接下来我们要遍历链表。遍历的顺序是从头到尾的顺序,可输出的顺序却是从尾到头。也就是说第一个遍历到的结点最后一个输出,而最后一个遍历到的结点第一个输出。 这就是典型的“后进先出”,我们可以用栈实现这种顺序。每经过一个结点的时候,把该结点放到一个栈中。当遍历完整个链表后,再从栈顶开始逐个输出结点的值,此时输出的结点的顺序已经反转过来了。这种思路的实现代码如下:

代码语言:cpp

/**
 * 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> vec= {};
        stack<ListNode*> s;
        ListNode * node = head;
        while(node!=NULL){    //循环将节点压入堆栈直到为空
            s.push(node);
            node = node->next;
        }
        while(!s.empty()){    //循环弹出,将栈顶元素压到vector后续输出
            vec.push_back(s.top()->val);
            s.pop();
        }
        return vec;
    }
};

24 / 24 个通过测试用例

状态:通过

执行用时: 0 ms

内存消耗: 8.7 MB

1.堆栈:先进后出,后进先出。注意区分队列的区别,队列:先进先出。 

  • 时间复杂度 O(N): 入栈和出栈共使用 O(N) 时间
  • 空间复杂度 O(N): 辅助栈 stack 和数组 vec 共使用 O(N) 的额外空间

方法三:简短递归法 

既然想到了用栈来实现这个函数,而递归在本质上就是一个栈结构,于是很自然地又想到了用递归来实现。要实现反过来输出链表,我们每访问到一个结点的时候,先递归输出它后面的结点,再输出该结点自身,这样链表的输出结果就反过来了。基于这样的思路,不难写出如下代码:

代码语言:cpp

/**
 * 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) {
        if(!head)
            return {};
        vector<int> a=reversePrint(head->next);    //直到指针为空时停止递归
        a.push_back(head->val);
        return a;
    }
};

 24 / 24 个通过测试用例

状态:通过

执行用时: 11 ms

内存消耗: 10.9 MB

  • 时间复杂度 O(N): 遍历链表,递归 N 次
  • 空间复杂度 O(N): 系统递归需要使用 O(N) 的栈空间
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

For L9L

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值