判断一个单向链表中是否有环
2015-11-23 23:04
239 查看
题目分析
这是一道经典的面试题,据说还是从微软传出来的,我们来看看这个问题的通用解法——快慢指针,用两个指针pSlow和pFast,就是一个慢指针一个快指针,慢的一次向后跳一步,快的一次向后跳两步,什么时候快的追上慢的了,即当(pSlow == pFast)时就表示有环,若pFast快指针先到了结尾则表示无环,实现的代码如下:struct listtype { int data; listtype * next; }; int find_cicle(listtype *head) { if (head == NULL) return -1; listtype *pFast = head; listtype *pSlow = head; while (pFast && pFast->next) { pFast = pFast->next->next; pSlow = pSlow->next; if (pFast == pSlow) return 1; } return 0; }
代码简析
调用函数返回值为1时,表示单向链表有环;调用函数返回值为0时,表示单向链表无环;
调用函数返回值为-1时,表示单向链表无环为空;
其中返回0和-1可以合并成一种情况,都是无环。
后续
指针遍历按道理来说这个问题到这应该是完美了,但是看着这个解法你有没有想过为什么要这么做,我就是这么较真,我就是想知道不这么做到底能不能行,难道这么做效率要高吗?我画了好几次,无论是奇数个节点的环还是偶数个节点的环但没有发现效率提高在哪?难道这么些仅仅是为了好玩?我用一个指针记录一下头指针,然后用一个指针遍历链表,找到了就有环,找不到就无环,难道这样不行吗?这样看着看着我突然想明白了,原来我一直都理解错了,我一直所尝试的环都是左侧图一这种,而真正的链表可能是右侧图二这种,好吧分析到这,指针简单的遍历肯定得pass掉了……
记录访问点
看到图二你或许又想到了方法,把访问过的节点记录一下,然后遍历新节点的时候逐一比较,这个方法可行……,但是咱们是不是还要考虑一下时间复杂度和空间复杂度啊,一共n个节点,当访问第2个节点的时候遍历访问过的1个节点,当访问第3个节点的时候遍历访问过的2个节点……以此类推,当访问第n个节点的时候遍历访问过的n-1个节点,貌似时间复杂度是O(n 2 ),再考虑考虑空间上市不是要存储n个节点信息需要O(n)啊。费时又费力啊,难道你还要把HashTable、HashSet搬出来吗?是时候放弃了,还是选择最初咱们看到的这种方法吧,时间上好像是O(n),空间上完全是O(1)的秒杀啊,不过具体的时间复杂度大家还要仔细考虑一下,肯定是小于等于n次比较的,大家可以算算平均值……,有什么好的想法和建议要告诉我哦,欢迎大家批评指正。
相关文章推荐
- Redis中实现查找某个值的范围
- 批量文件查找替换功能的vbs脚本
- WinForm实现按名称递归查找控件的方法
- 一个用vbs查找硬盘所有分区中的指定程序的代码
- 浅析Node.js查找字符串功能
- C++二分法在数组中查找关键字的方法
- WinForm自定义函数FindControl实现按名称查找控件
- Shell脚本学习指南之查找与替换介绍
- php实现指定字符串中查找子字符串的方法
- C#查找对象在ArrayList中出现位置的方法
- jquery 查找新建元素代码
- Oracle 查找与删除表中重复记录的步骤方法
- SQL Server根据分区表名查找所在的文件及文件组实现脚本
- PHP学习之字符串比较和查找
- python查找指定具有相同内容文件的方法
- 二叉查找树的插入,删除,查找
- php查找指定目录下指定大小文件的方法
- php查找字符串出现次数的方法
- php在数组中查找指定值的方法
- php实现在多维数组中查找特定value的方法