经典面试题之单链表找环
2014-05-14 22:01
260 查看
大概的题意是,给出一个单向链表的头节点,求这么链表是否有环。有环的定义是,链表的尾节点指向了链接中间的某个节点。单链表的定义如下:
这道题目还有一些变种,比如求链接的长度,求链表的尾节点等,不过大同小异。第一次听说这个题目,是在大三的时候,从一个刚面完试的学长那里。他当时的做法是对这个链表求逆,求逆的结果链表上每一个指针都反向,如果逆序完之后,链表的头节点不变,即说明链接有环。具体的证明过程略。这个方法的复杂也是O(N),但是需要修改原链表,或者使用O(N)的额外空间。
标准做法是使用两个指针,一个每次往前走2步,一个每次往前走1步,如果两个指针相遇,即说明链表有环,时间复杂度为O(N),空间复杂度为O(1)。
代码如下:
测试数据也比较简单,考虑一下空指针、单个节点成环、整条链表成环就可以了:
struct Node { Node(): next(NULL) {} Node *next; };
这道题目还有一些变种,比如求链接的长度,求链表的尾节点等,不过大同小异。第一次听说这个题目,是在大三的时候,从一个刚面完试的学长那里。他当时的做法是对这个链表求逆,求逆的结果链表上每一个指针都反向,如果逆序完之后,链表的头节点不变,即说明链接有环。具体的证明过程略。这个方法的复杂也是O(N),但是需要修改原链表,或者使用O(N)的额外空间。
标准做法是使用两个指针,一个每次往前走2步,一个每次往前走1步,如果两个指针相遇,即说明链表有环,时间复杂度为O(N),空间复杂度为O(1)。
代码如下:
bool TestCircle(Node *p){ if (p == NULL){ return false; } if (p->next == NULL){ return false; } if (p->next == p){ return true; } Node *y = p->next; Node *x = p->next->next; while(x != NULL && y != NULL){ x = x->next; if (x == NULL) break; x = x->next; y = y->next; if (x == y) break; } return x == y; }
测试数据也比较简单,考虑一下空指针、单个节点成环、整条链表成环就可以了:
void RunTest() { Node *p = NULL; Node *q = NULL; cout << "empty list" << endl; cout << TestCircle(NULL) << endl; cout << "one node not circle" << endl; p = new Node; cout << TestCircle(p) << endl; delete p; p = NULL; cout << "one node circle" << endl; p = new Node; p->next = p; cout << TestCircle(p) << endl; delete p; p = NULL; cout << "two nodes not circle" << endl; p = new Node; p->next = new Node; cout << TestCircle(p) << endl; delete p->next; delete p; p = NULL; cout << "two nodes circle" << endl; p = new Node; p->next = new Node; p->next->next = p; cout << TestCircle(p) << endl; delete p->next; delete p; p = NULL; cout << "two nodes circle case 2" << endl; p = new Node; p->next = new Node; p->next->next = p->next; cout << TestCircle(p) << endl; delete p->next; delete p; p = NULL; cout << "5 nodes not circle" << endl; p = new Node; q = p; for (int i = 0; i < 4; ++i) { q->next = new Node; q = q->next; } cout << TestCircle(p) << endl; while (p->next != NULL) { q = p->next->next; delete p->next; p->next = q; } delete p; p = NULL; cout << "5 nodes circle" << endl; p = new Node; q = p; for (int i = 0; i < 4; ++i) { q->next = new Node; q = q->next; } q->next = p; cout << TestCircle(p) << endl; q->next = NULL; while (p->next != NULL) { q = p->next->next; delete p->next; p->next = q; } delete p; p = NULL; cout << "5 nodes circle case 2" << endl; p = new Node; q = p; for (int i = 0; i < 4; ++i) { q->next = new Node; q = q->next; } q->next = p->next->next; cout << TestCircle(p) << endl; q->next = NULL; while (p->next != NULL) { q = p->next->next; delete p->next; p->next = q; } delete p; p = NULL; cout << "5 nodes circle case 3" << endl; p = new Node; q = p; for (int i = 0; i < 4; ++i) { q->next = new Node; q = q->next; } q->next = q; cout << TestCircle(p) << endl; q->next = NULL; while (p->next != NULL) { q = p->next->next; delete p->next; p->next = q; } delete p; p = NULL; cout << "100000000 nodes not circle" << endl; p = new Node; q = p; for (int i = 0; i < 100000000; ++i) { q->next = new Node; q = q->next; } cout << TestCircle(p) << endl; while (p->next != NULL) { q = p->next->next; delete p->next; p->next = q; } delete p; p = NULL; cout << "100000000 nodes circle" << endl; p = new Node; q = p; for (int i = 0; i < 100000000; ++i) { q->next = new Node; q = q->next; } q->next = p; cout << TestCircle(p) << endl; q->next = NULL; while (p->next != NULL) { q = p->next->next; delete p->next; p->next = q; } delete p; p = NULL; cout << "100000000 nodes circle case 2" << endl; p = new Node; q = p; for (int i = 0; i < 100000000; ++i) { q->next = new Node; q = q->next; } Node *t = p; for (int i = 0; i < 16; ++i) { t = t->next; } q->next = t; cout << TestCircle(p) << endl; q->next = NULL; while (p->next != NULL) { q = p->next->next; delete p->next; p->next = q; } delete p; p = NULL; }
相关文章推荐
- 【单链表经典面试题解析三】在无头单链表的一个非头节点前插入一个节点(要求不能遍历单链表)
- 经典面试题之单链表实现约瑟夫环(杀人游戏)
- 单链表经典面试题
- 单链表的一些经典面试题
- 单链表经典面试题
- 顺序表链表经典面试题之逆序打印单链表
- 经典面试题之逆序打印单链表
- 经典面试题】寻找单链表倒数第n个节点_C/C++
- 【经典面试题】寻找单链表倒数第n个节点_C/C++
- 单链表的几道经典面试题(2)
- 【经典面试题】寻找单链表倒数第n个节点
- 单链表的几道经典面试题(1)
- 经典算法面试题(二):用递归法把二叉树的叶子结点按从左到右的顺序连成一个单链表
- 【单链表经典面试题解析一】从尾到头打印单链表
- 单链表的一些经典面试题
- 运行时异常与一般异常有何异同? —— Java经典面试题系列
- C语言学习趣事_经典面试题系列_3
- 李洪强经典面试题35
- SQL经典面试题及答案
- 经典面试题(二)附答案 算法+数据结构+代码 微软Microsoft、谷歌Google、百度、腾讯