《剑指offer》面试题6:从尾到头打印链表(C++实现)

题目描述

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

思路一:反转链表后再读出

看到这道题我们很自然而然的就会想到,既然让我们从尾到头进行一个打印,那很明显,我们可以先把链表进行反转,再从头到尾打印一遍即可。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
 vector<int> printListFromTailToHead(ListNode* head) {
     vector<int> result;
     //反转链表
     ListNode* pre = NULL;
     ListNode* cur = head;
     while(cur != NULL){
        ListNode* next = cur->next;//存放当前节点的下一节点
        cur->next = pre;//cur从指向next,改为指向pre  
        pre = cur ;//右移
        cur = next;//下一节点赋值给当前节点
             }
     
     //反转完成时,
     while(pre!= nullptr){
         result.push_back(pre->val);
         pre = pre->next;
     }
     return result;
    }
        

    
};

思路二:用栈去实现

如果我们不希望对于输入的数据进行修改。那我们可以在从头到尾遍历链表的时候,用栈记录下当前节点的值。当完成链表的遍历的时候,然后根据栈先进后出的特性,从栈顶开始逐个输出节点的值,那么就实现了从尾到头打印链表的目的。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
    stack<int> nodes;//存放节点的值
    vector<int> result;
    ListNode* pNode = head;
    
    //用栈去记录数值
    while(pNode!=nullptr){
        nodes.push(pNode->val);
        pNode = pNode->next;
    }
    
    //用vertor去读取从栈顶到栈底的元素
    while(!nodes.empty()){
        result.push_back(nodes.top());
        nodes.pop();
    }
        return result;

思路三:递归实现

既然我们想到了用栈去实现这个函数,而递归的本质是一个栈的结构。所以我们很自然地又想到了用递归去实现。
思路就是,我们先输出当前节点的下一节点的值,再输出当前节点的值,即可完成。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> result;
    vector<int> printListFromTailToHead(ListNode* head) {
    if(head != nullptr)
    {
       if(head->next != nullptr)
      {
        printListFromTailToHead(head->next);
      }
      result.push_back(head->val);
        
    }
    return result;

    }
};

递归会一直执行到链表的最后一个节点,然后发现下一节点为空,不再进行调用,然后把当前节点的值添加进result之中。然后添加完后返回递归调用的上一级,添加它的上一个节点的值,依次类推,直到添加完成链表所有的值。

小结

思路一引起了输入的改变。
思路三递归的代码看上去很简洁,但是如果当链表非常长的时候,就会导致函数调用的层级很深,从而有可能导致函数调用栈溢出。
针对代码的鲁棒性,而言最好的是思路二。

参考文献

《剑指offer》

牛课网刷题链接link.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值