转帖:关于链表操作不得不看的经典问题
2011-06-18 21:21
323 查看
本文出自 “bluefish” 博客,请务必保留此出处/article/7326093.html
下面是几个关于链表的非常经典的问题与实现,是在《程序员面试攻略》中看到的,由于实在是太经典了,所以忍不住在这里贴下。
问题1:给定一个单项链表,设计一个时间优化并且时间优化的算法,找出该链表的倒数第m个元素。当m=0时,返回链表的最后一个元素。
[分析:用双指针来实现,两指针间隔m。同步移动两指针,当前一个指针为该链表tail时,后一个指针就为要找的元素]
问题2:从一个标准的双向链表开始。假定除了next指针和previous指针之外,每个元素保存了一个child指针,它可能指向一个独立的双向链表,也可能为空。这些子链表又可能有一个或多个子链表,如此下去,得到了一个多层次的数据结构。将这个链表展平,使得所有节点都出现在一个一层的双向链表中。每个节点定义如下:
[分析:从第一层链表头开始遍历链表,如果有第二层链表,则将其放到第一层链表尾。这样其实第一层链表尾一直在往后移动,原来的第一层在遍历完后就可以直接遍历第二层了,依此类推就可以完成题目要求,前提要有一个指向尾指针的指针]
问题3:编写一个函数,接受链表的头指针作为参数,确定该链表是循环的还是非循环的。如果链表是非循环的,函数返回false;如果是循环的,函数返回true。不能以任何方式修改该链表。
[分析:用双指针实现,一个用step=1前进,一个用step=2前进。看两个指针是否能相遇]
下面是几个关于链表的非常经典的问题与实现,是在《程序员面试攻略》中看到的,由于实在是太经典了,所以忍不住在这里贴下。
问题1:给定一个单项链表,设计一个时间优化并且时间优化的算法,找出该链表的倒数第m个元素。当m=0时,返回链表的最后一个元素。
[分析:用双指针来实现,两指针间隔m。同步移动两指针,当前一个指针为该链表tail时,后一个指针就为要找的元素]
Element * FindMToLastElement( Element * head, int m) { Element * current, * mBehind; int i; current = head; for( i = 0; i < m; i++) { if(current->next) { current = current->next; } else { return NULL; } } mBehind = head; while(current->next) { current = current->next; mBehind = mBehind->next; } return mBehind; }
问题2:从一个标准的双向链表开始。假定除了next指针和previous指针之外,每个元素保存了一个child指针,它可能指向一个独立的双向链表,也可能为空。这些子链表又可能有一个或多个子链表,如此下去,得到了一个多层次的数据结构。将这个链表展平,使得所有节点都出现在一个一层的双向链表中。每个节点定义如下:
typedef struct Node{ struct Node * next; struct Node * prev; struct Node * child; int value; }Node;
[分析:从第一层链表头开始遍历链表,如果有第二层链表,则将其放到第一层链表尾。这样其实第一层链表尾一直在往后移动,原来的第一层在遍历完后就可以直接遍历第二层了,依此类推就可以完成题目要求,前提要有一个指向尾指针的指针]
void FlattenList( Node * head, Node ** tail) { Node * curNode = head; while( curNode ) { if(curNode->child) { Append(curNode->child, tail); } curNode = curNode->next; } } void Append( Node * child, Node ** tail) { Node * curNode; (*tail)->next = child; child-prev = *tail; for(curNode = child; curNode->next; curNode = curNode->next) { } *tail = curNode; }
问题3:编写一个函数,接受链表的头指针作为参数,确定该链表是循环的还是非循环的。如果链表是非循环的,函数返回false;如果是循环的,函数返回true。不能以任何方式修改该链表。
[分析:用双指针实现,一个用step=1前进,一个用step=2前进。看两个指针是否能相遇]
bool DetermineTermination( Node * head) { Node * fast, * slow; fast = slow = head; while(true) { if(!fast || !fast->next) { return false; } else if(fast == slow || fast->next == slow) { return true; } else { slow = slow->next; fast = fast->next->next; } } }
相关文章推荐
- 关于动态存储分配函数的调用,在已经过排序的数组中查找及删除内容的操作,余数的分析,删除字符数组中的空格,对链表的逆置,在源字符串中查找子字符串的个数,函数指针以及函数的调用,循环赋值带来的问题以及插入
- 关于链表操作的问题
- 数列问题 , 经典的链表操作
- 关于链表的一些经典问题以及相关面试题
- 关于链表操作一些有趣的问题!
- 数列问题 , 经典的链表操作
- c++关于结构体动态链表初始化添加删除操作代码
- 关于反转链表的问题
- 【日常小坑】关于python3操作数据库实用占位符传入引用变量问题,做个Mark(python学习第一天)
- 关于POI操作excel中带公式的的单元格问题
- javascript关于运动的各种问题经典总结
- 关于Objective-C 对象release操作的一个小问题探讨
- 单链表面试经典问题
- 关于PicoBlaze 读操作的一个问题的讨论(一)
- 关于删除链表元素的操作
- 关于EXCEL操作的问题
- AJAXPro 关于session和application的操作问题
- 【C++深度剖析教程15】经典问题解析之关于string的疑问
- --->关于链表的增删改查的基本操作
- 一道经典的C++题,关于分钱的问题,适合新手阅读(黑客X档案论坛题目)