这个是高频的面试题,今天总结了一些。反转链表用三个指针实现,返回新链表的头节点;而从尾到头打印,应用栈实现,返回vector整个链表。

//题目描述
//
//输入一个链表,反转链表后,输出链表的所有元素。

struct ListNode
{
    int val;
    struct ListNode *next;
    ListNode(int x) :val(x), next(nullptr){}
};

//思路
//在反转链表的时候,我们很容易想到让当前结点的next指向前一个结点,
//但是这样做了之后这个节点原本next所指的结点就找不回了,所以每次我们都要保存新的前一结点,
//当前结点和下一结点三个指针,只要下一结点为空,那么我们就到了原本结点的尾部,这时正是新链表的头部
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {

        ListNode *current = pHead;
        ListNode *pre = nullptr;
        ListNode *pNewNode = nullptr;
        if (pHead == nullptr)
        {
            return nullptr;
        }
        while (current != nullptr)  //当前结点不为空
        {
            ListNode *pnext = current->next; //当前结点的后继
            if (pnext == nullptr)
            {
                pNewNode = current;  //最后结点,即反转链表的头节点
            }
            current->next = pre; //当前结点的后继转为前驱
            pre = current;  //前驱转为当前结点
            current = pnext;  //当前结点向后移
        }
        return pNewNode;
    }
};

//1、三个指针在链表上同时滑动,比较容易想到但是编码略复杂
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if (pHead == nullptr) return nullptr;
        if (pHead->next == nullptr) return pHead;

        ListNode *pBefore = pHead, *p = pHead->next, *pAfter = p->next;
        while (pAfter) {
            p->next = pBefore; // reverse
            pBefore = p;
            p = pAfter;
            pAfter = pAfter->next;
        }
        p->next = pBefore; //完成最后一个结点的前驱
        pHead->next = nullptr; //尾结点后继为空
        return p;
    }
};

//2、从原链表的头部一个一个取节点并插入到新链表的头部
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if (pHead == nullptr) return nullptr;
        ListNode* head = pHead;
        pHead = pHead->next;
        head->next = nullptr; //此时的head为尾结点
        while (pHead) {
            ListNode *next = pHead->next;
            pHead->next = head;
            head = pHead; //
            pHead = next;
        }
        return head;
    }
};

//使用一个栈来解决问题,C++

#include<stack>
using namespace std;
class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if (pHead == nullptr || pHead->next == nullptr)
        {
            return pHead;
        }
        ListNode * p = pHead;
        ListNode * newHead;
        stack<ListNode *> stack1;
        while (p->next != NULL)
        {
            stack1.push(p);
            p = p->next;
        }
        newHead = p;
        while (!stack1.empty())
        {
            p->next = stack1.top();
            p = p->next;
            stack1.pop();
        }
        p->next = NULL;
        return newHead;
    }
};

//题目描述
//
//输入一个链表,从尾到头打印链表每个节点的值。
//输入描述 :
//输入为链表的表头
//
//
//输出描述 :
//输出为需要打印的“新链表”的表头
#include<vector>
class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {

        //std::stack<ListNode*> nodes;

        // ListNode *pNode = head;
        // while(pNode != NULL)
        // {
        //      nodes.push(head);
        //      head = head->next;
        // }

        //  while(!nodes.empty())
        //  {
        //     head = nodes.top();
        //     printf("%d\t" ,head->val);
        //     nodes.pop();
        //  }

        vector<int> dev1;
        if (head != NULL)
        {
            if (head->next != NULL)
            {
                dev1 = printListFromTailToHead(head->next);
            }
            dev1.push_back(head->val);
        }
        return dev1;

    }
};

class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head) {
        //利用栈的逆序输出特性
        stack<int> stack;
        vector<int> vector;
        struct ListNode *p = head;
        if (head != NULL) {
            stack.push(p->val);
            while ((p = p->next) != NULL) {
                stack.push(p->val);
            }
            while (!stack.empty()) {
                vector.push_back(stack.top());
                stack.pop();
            }
        }
        return vector;
    }

};

/***
*从原理上来说,借助栈会使得问题的解决思路非常简单明了。
*注意函数的返回类型是int类型的vector
*/
class Solution {
public:
    vector<int> printListFromTailToHead(struct ListNode* head)
    {
        vector<int> vec;         //声明一个vector存放Node的int类型的val值
        std::stack<ListNode *>nodes;
        ListNode *pNode = head;
        //遍历入栈
        while (pNode != NULL)
        {
            nodes.push(pNode);    //遍历所有节点,将结点压入栈中
            pNode = pNode->next;
        }
        //遍历出栈
        while (!nodes.empty())
        {
            pNode = nodes.top();        //定义的结点指针始终指向栈顶,取出栈顶结点的val值存入到定义的vec中,然后弹出栈顶元素。由栈顶往栈底遍历
            vec.push_back(pNode->val);
            nodes.pop();
        }
        return vec;    //返回值为int型的vector
    }
};

offer--链表反转和从尾到头打印链表的更多相关文章

  1. 剑指Offer - 九度1511 - 从尾到头打印链表

    剑指Offer - 九度1511 - 从尾到头打印链表2013-11-29 21:08 题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入: 每个输入文件仅包含一组测试样例.每一组测试案例 ...

  2. JS 剑指Offer(四) 从尾到头打印链表

    题目:输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 首先定义一下链表中的节点,关于链表这个数据结构在另外一篇文章中会详细讲 function ListNode(val) { t ...

  3. 剑指offer【03】- 从尾到头打印链表(4种实现方法)

    题目:从尾到头打印链表 考点:链表 题目描述:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 法一:ArrayList头插法 /** * public class ListNode ...

  4. 【Offer】[6] 【从尾到头打印链表】

    题目描述 思路分析 Java代码 代码链接 题目描述 从尾到头打印链表,将其添加到ArrayList当中输出 思路分析 递归的思路 利用栈 Java代码 public class Offer006 { ...

  5. 剑指offer(3)从尾到头打印链表

    题目描述 输入一个链表,从尾到头打印链表每个节点的值. 题目分析 比较简单,主要注意下从尾到头,可以用栈可以用递归,我给出我比较喜欢的代码吧 代码 /* function ListNode(x){ t ...

  6. 【剑指Offer】3、从尾到头打印链表

      题目描述:   输入一个链表,按链表值从尾到头的顺序返回一个ArrayList.   解题思路:   (三种方法:借助栈.递归.列表的首位插入)   从头到尾打印链表比较简单,从尾到头很自然的可以 ...

  7. 剑指offer第二版-6.从尾到头打印链表

    描述:输入一个链表的头节点,从尾到头打印每个节点的值. 思路:从尾到头打印,即为“先进后出”,则可以使用栈来处理:考虑递归的本质也是一个栈结构,可递归输出. 考点:对链表.栈.递归的理解. packa ...

  8. 剑指offer(5)——从尾到头打印链表

    题目: 输入一个链表的头结点,从尾到头反过来打印出每个结点的值.结点定义如下: public class ListNode { int val; ListNode next = null; ListN ...

  9. 剑指Offer编程题3——从尾到头打印链表

    题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList.   题目解析 方法1:建立两个vector,第一个用来存储正向访问的数据,第二个用来反向存储. /** * struct L ...

随机推荐

  1. 《c程序设计语言》读书笔记--统计换行数,空格数,tab数

    #include <stdio.h> int main() { int spa = 0,lin = 0,tab = 0; int c; /* spa代表空格个数,tab代表制表符个数,li ...

  2. hdu - 2102 A计划 (简单bfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=2102 题目还是不难,注意起点一定是(0,0,0),然后到达P点时间<=t都可以. 用一个3维字符数组存储图 ...

  3. urllib.request ProxyHandler

    import urllib.request proxy_support = urllib.request.ProxyHandler({}) opener = urllib.request.build_ ...

  4. 关于在c#中引用外部dll文件,在页面中找不到命名空间

    最近在项目中碰到这样的问题,经过搜索,发现是vs2010的版本不对,VS默认的版本是.NET Framework 4 Client Profile,需要将他更改为.NET Framework 4 版本 ...

  5. 收藏一些python的小技能

    例子1:For .. else 语法 foo=[2,1] for i in foo: if i == 0: break else: print("i was never 0") 例 ...

  6. Codeforces Beta Round #97 (Div. 1)

    B 判矩阵的时候 出了点错 根据点积判垂直 叉积判平行 面积不能为0 #include <iostream> #include<cstdio> #include<cstr ...

  7. zoj 3329 One Person Game (有环 的 概率dp)

    题目链接 这个题看的别人的思路,自己根本想不出来这种设方程的思路. 题意: 有三个骰子,分别有k1,k2,k3个面. 每次掷骰子,如果三个面分别为a,b,c则分数置0,否则加上三个骰子的分数之和. 当 ...

  8. 如何将SQLite数据库(dictionary.db文件)与apk文件一起发布

      可以将dictionary.db文件复制到Eclipse Android工程中的res\raw目录中,如图1所示.所有在res\raw目录中的文件不会被压缩,这样可以直接提取该目录中的文件.使 用 ...

  9. ionic中极光推送的集成

    1.到极光官网注册账号,新建应用获得appkey. 详见:https://www.jiguang.cn/app/list 2.引入jpush插件 详见:https://github.com/jpush ...

  10. ios多手势事件

    开发ios应用时我们经常用到多手势来处理事情,如给scrollView增加点击事件,scrollView不能响应view的touch事件,但有时候却要用到多手势事件,那么我们可以给这个scrollVi ...