判断链表是否带环?若带环求环的长度?若带环求环的入口点?
2017-07-17 11:36
423 查看
链表就跟他的名字一样,是一串串起来的链,具体是什么样子在程序中是不能直观的看到的,因为每个节点的地址并不是连续的,但是我们可以通过指针,将其进行遍历访问。
今天我们来讨论一下,一个链表是否带环?若带环,那么环的长度又是多少?环的入口?
判断一个链表是否带环,返回值最直接的应该就是bool,在C++中bool即真假判断。
第二版
因为如果带环的话,后面可能还要进行相应的使用,所以我想到了ListNodeT*作为返回值,这样可以得到是否带环的判断结果,又可以拿到带环的节点
网上有一种用到了pair
pair使用的原则,应该是上面两者的综合吧。
设置节点
为了统一,做typedef
判断是否带环
通过快慢指针法,判断是否带环,好比跑步,假设两个人在跑步,且速度不变,一个快,一个慢,则在一定时间后,两个人肯定会再次相遇。
判断带环函数返回的节点肯定是在换中的,当一个节点一直走,相遇的节点不动是,再次相遇,就可以求得环的长度
这里是一个数学公式的实践,交点node到入口点的距离=头指针到连接点的距离,因此,分别从交点、头指针开始走,相遇的那个点就是连接
假设链表总长为L,头节点到入口点的距离为a,入口点到快慢指针交点距离为x,环的长度为R,现在假设慢指针走了S步与快指针相遇,
s = a + x;
那么快指针走了2S步,
2s = a + nr + x;
就可以得到:a + x = nr;
->a = nr - x;
可以看出来,头节点到入口点的距离等于,交点到入口点的距离,那我们让两个指针,一个从交点走,一个从头节点走,最后一定在入口点相遇。
测试
今天我们来讨论一下,一个链表是否带环?若带环,那么环的长度又是多少?环的入口?
一个链表是否带环?
第一次拿到这道题的时候,我的函数原型是这样的bool isCircle(ListNodeT* head)
判断一个链表是否带环,返回值最直接的应该就是bool,在C++中bool即真假判断。
第二版
ListNodeT* isCircle(ListNodeT* head)
因为如果带环的话,后面可能还要进行相应的使用,所以我想到了ListNodeT*作为返回值,这样可以得到是否带环的判断结果,又可以拿到带环的节点
网上有一种用到了pair
pair<Node<int>*, bool> isCircle(ListNodeT* head)
pair使用的原则,应该是上面两者的综合吧。
设置节点
template<class T> struct ListNode { T _data; ListNode<T>* _next; ListNode(T x = T()) :_data(x) , _next(NULL) {} };
为了统一,做typedef
typedef ListNode<int> ListNodeT;
判断是否带环
ListNodeT* isCircle(ListNodeT* head) { if (head == NULL) { printf("is no node in this list\n"); return NULL; } ListNodeT* first = head; ListNodeT* second = head; if (head->_next == NULL) { printf("List isn't have circle\n"); return NULL; } while (first->_next) { first = first->_next; second = second->_next->_next; if (first == second) { printf("List hava a circle\n"); return first; } } printf("List isn't have circle\n"); return NULL; }
通过快慢指针法,判断是否带环,好比跑步,假设两个人在跑步,且速度不变,一个快,一个慢,则在一定时间后,两个人肯定会再次相遇。
求带环环的长度
int length(ListNodeT* head,ListNodeT* node) { ListNodeT* cur = node->_next; int count = 1; while (cur != node) { count++; cur = cur->_next; } return count; }
判断带环函数返回的节点肯定是在换中的,当一个节点一直走,相遇的节点不动是,再次相遇,就可以求得环的长度
求环的入口
ListNodeT* FindLoopPort(ListNodeT*head, ListNodeT* node) { ListNodeT* cur = head; while (cur != node) { cur = cur->_next; node = node->_next; } return cur; }
这里是一个数学公式的实践,交点node到入口点的距离=头指针到连接点的距离,因此,分别从交点、头指针开始走,相遇的那个点就是连接
假设链表总长为L,头节点到入口点的距离为a,入口点到快慢指针交点距离为x,环的长度为R,现在假设慢指针走了S步与快指针相遇,
s = a + x;
那么快指针走了2S步,
2s = a + nr + x;
就可以得到:a + x = nr;
->a = nr - x;
可以看出来,头节点到入口点的距离等于,交点到入口点的距离,那我们让两个指针,一个从交点走,一个从头节点走,最后一定在入口点相遇。
测试
int main() { ListNodeT* head = new ListNodeT(1); ListNodeT* node1 = new ListNodeT(2); ListNodeT* node2 = new ListNodeT(3); head->_next = node1; node1->_next = node2; node2->_next = head; ListNodeT* ret = NULL; ret = isCircle(head); if (ret !=NULL) cout << length(head,ret) << endl; if (ret != NULL) cout << FindLoopPort(head, ret) << endl; ListNodeT* node = FindLoopPort(head, ret); cout << node->_data << endl; system("pause"); return 0; }
相关文章推荐
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- -判断链表是否带环?若带环求环的长度?若带环求环的入口点
- 剑指offer 15---判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 剑指offer面试题-判断链表是否带环并求环的入口点和环的长度
- 判断链表是否带环?若带环求环的长度?求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?并计算以上每个问题的时间复杂度?
- 链表面试题----判断一个单链表是否带环,若带环,求入口点和环的长度
- 判断链表是否带环,若带环求环的长度,若带环求环的入口点
- 链表--判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 链表面试题之判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 剑指offer--判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断单链表是否带环? 若带环, 求环的长度? 求环的入口点?
- 笔试,面试,C/C++,判断单链表是否带环?若带环,求环长度,求环入口点(两种方法)
- 17_7_15:判断链表是否有环+求环的长度+求环的入口。设计不能被继承的类,只能堆/栈上创建对象的类
- 判断单链表是否带环?若带环,求环的长度,求环的入口点
- 判断链表是否带环,以及环的入口
- day03之判断链表带环以及求环的长度及环的入口点+一个类不能被继承及只能分别在栈堆上创建对象