题目:输入一个链表的头结点,反转该链表,并返回反转后链表的头结点。链表结点定义如下:

struct ListNode
{int       m_nKey;ListNode* m_pNext;
};

分析:这是一道广为流传的微软面试题。由于这道题能够很好的反应出程序员思维是否严密,在微软之后已经有很多公司在面试时采用了这道题。

为了正确地反转一个链表,需要调整指针的指向。与指针操作相关代码总是容易出错的,因此最好在动手写程序之前作全面的分析。在面试的时候不急于动手而是一开始做仔细的分析和设计,将会给面试官留下很好的印象,因为在实际的软件开发中,设计的时间总是比写代码的时间长。与其很快地写出一段漏洞百出的代码,远不如用较多的时间写出一段健壮的代码。

为了将调整指针这个复杂的过程分析清楚,我们可以借助图形来直观地分析。假设下图中l、m和n是三个相邻的结点:

a?b?…?l  mànà…

假设经过若干操作,我们已经把结点l之前的指针调整完毕,这些结点的m_pNext指针都指向前面一个结点。现在我们遍历到结点m。当然,我们需要把调整结点的m_pNext指针让它指向结点l。但注意一旦调整了指针的指向,链表就断开了,如下图所示:

a?b?…l?m  nà…

因为已经没有指针指向结点n,我们没有办法再遍历到结点n了。因此为了避免链表断开,我们需要在调整m的m_pNext之前要把n保存下来。

接下来我们试着找到反转后链表的头结点。不难分析出反转后链表的头结点是原始链表的尾位结点。什么结点是尾结点?就是m_pNext为空指针的结点。

基于上述分析,我们不难写出如下代码:

///
// Reverse a list iteratively
// Input: pHead - the head of the original list
// Output: the head of the reversed head
///
ListNode* ReverseIteratively(ListNode* pHead)
{ListNode* pReversedHead = NULL;ListNode* pNode = pHead;ListNode* pPrev = NULL;while(pNode != NULL){// get the next node, and save it at pNextListNode* pNext = pNode->m_pNext;// if the next node is null, the currect is the end of original // list, and it's the head of the reversed listif(pNext == NULL)pReversedHead = pNode;// reverse the linkage between nodespNode->m_pNext = pPrev;// move forward on the the listpPrev = pNode;pNode = pNext;}return pReversedHead;
}

扩展:本题也可以递归实现。感兴趣的读者请自己编写递归代码。

本文已经收录到《剑指Offer——名企面试官精讲典型编程题》一书中,有改动,书中的分析讲解更加详细。欢迎关注。

博主何海涛对本博客文章享有版权。网络转载请注明出处http://zhedahht.blog.163.com/。整理出版物请和作者联系。对解题思路有任何建议,欢迎在评论中告知,或者加我微博http://weibo.com/zhedahht或者http://t.163.com/zhedahht与我讨论。谢谢。

程序员面试题精选100题(19)-反转链表[数据结构]相关推荐

  1. [程序员面试题精选100题]19.反转链表

    题目 输入一个链表的头结点,反转该链表,并返回反转后链表的头结点. 分析 假设经过若干操作,我们已经把结点 pre之前的指针调整完毕,这些结点的next指针都指向前面一个结点.现在我们遍历到结点cur ...

  2. 程序员面试题精选100题(09)-链表中倒数第k个结点[数据结构]

    题目:输入一个单向链表,输出该链表中倒数第k个结点.链表的倒数第0个结点为链表的尾指针.链表结点定义如下: struct ListNode {       int       m_nKey;      ...

  3. 程序员面试题精选100题(35)-两链表的第一个公共结点[数据结构]

    题目:两个单向链表,找出它们的第一个公共结点. 链表的结点定义为: struct ListNode { int         m_nKey; ListNode*   m_pNext; }; 分析:这 ...

  4. 程序员面试题精选100题(49)-复杂链表的复制[算法]

    题目:有一个复杂链表,其结点除了有一个m_pNext指针指向下一个结点外,还有一个m_pSibling指向链表中的任一结点或者NULL.其结点的C++定义如下: struct ComplexNode ...

  5. 程序员面试题精选100题(39)-颠倒栈[数据结构]

    题目:用递归颠倒一个栈.例如输入栈{1, 2, 3, 4, 5},1在栈顶.颠倒之后的栈为{5, 4, 3, 2, 1},5处在栈顶. 分析:乍一看到这道题目,第一反应是把栈里的所有元素逐一pop出来 ...

  6. 程序员面试题精选100题

    程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 比如将二元查找树   ...

  7. 程序员面试题精选100题:41-50解题报告

    程序员面试题精选100题(41)-把数组排成最小的数[算法]   题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个.例如输入数组{32,  321},则输出这两个能 ...

  8. [程序员面试题精选100题]13.第一个只出现一次的字符

    [题目] 在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b. [分析] [代码] /********************************* * 日期:2013- ...

  9. 程序员面试题精选100题(51)-顺时针打印矩阵

    // 程序员面试题精选100题(51)-顺时针打印矩阵.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h" #include <iostre ...

最新文章

  1. JavaScript 立即执行函数的两种写法
  2. 写一个算法统计在输入字符串中各个字符出现的频度
  3. 季节性时间序列数据分析_如何指导时间序列数据的探索性数据分析
  4. 1.10 编程基础之简单排序 06 整数奇偶排序 python
  5. ajax出错并返回整个页面html的问题,【提问】ajax请求返回整个html页面
  6. Source does not fit in dest
  7. winpe 服务器 维护,无垠PE维护系统v2017.04.30 ISO维护/网络版无广告
  8. 刷访问量新招[流量精灵]
  9. 【物联家居】第四章:传输协议--mqtt配置与测试
  10. 如何利用计算机打德文,如何在德语键盘上打问号
  11. 酷炫小程序相册源码,制作属于自己的相册,免费下载
  12. L - Ray in the tube Gym - 101911L (暴力)
  13. matlab中如何输入积分,在matlab中怎么输入特殊符号,Matlab的符号积分
  14. linux服务器停止步骤,停止和重新启动许可服务器的步骤
  15. 四叉树算法:iOS地图点标记聚合方案
  16. 接入交换机,汇聚交换机,核心交换机
  17. 腾讯面试:《警察抓小偷逻辑题》
  18. 送20本纸质书籍,包邮
  19. Multisim、proteus和protel的区别
  20. js修改身份证,手机号码为****的方法

热门文章

  1. 基于deep learning的快速图像检索(Deep Learning of Binary Hash Codes for Fast Image Retrieval)
  2. 基因组与数据整合:DNA应用开发正在临近
  3. linux 删除20日前数据,Linux 维护常用命令
  4. linux fedora14 u盘运行,Win7下Fedora 14 硬盘或U盘安装指南
  5. 实战并发编程 - 07循环等待死锁问题
  6. 深入理解分布式技术 - 探究缓存穿透、缓存击穿、缓存雪崩解决方案
  7. Elasticsearch-02CentOS7安装elasticsearch-head插件
  8. Oralce-清除数据的两种思路
  9. Spring JDBC-使用Spring JDBC访问数据库
  10. Apache-DBCP数据库连接池解读