剑指offer-15:单链表有趣问题-有环-环长度-环入口等(续)
来源:互联网 发布:word怎么合计数据 编辑:程序博客网 时间:2024/06/05 12:45
第15题要求找到倒数第k个结点。采用快慢出发不同的指针,卡出k-1的距离,当快指针到尾结点时,慢指针刚好在倒数第k个位置上。
还有一些相关题目比较有趣,类似的思路。
(1)求链表的中间结点
答:设置两个指针,移动快慢不同。快指针每次移动2步,慢指针每次移动1步。两者同时从头结点开始出发。当快指针到达尾结点时,走的路程是n,由于慢指针速度是其一半,则相同时间走的路程就是n/2,恰好位于链表的中间。
如果链表中的结点为奇数,则返回中间结点;如果链表中的结点为偶数,则返回中间两个结点的任意一个(前一个)。
// fast每次走2步,终点时:偶数时自身会为null,奇数时next会为nullwhile( fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next; }
(2)判断单向链表是否有环
答:若单链表有环,则可定义两个快慢指针。和操场跑圈类似,若有环,则快指针势必会追上慢指针,此时就是有环。若没有环,快指针会走到尾结点也不会和慢指针相遇,此时无环。
代码:
bool isLoop(pNode *pHead) { pNode *fast = pHead; pNode *slow = pHead; //如果无环,则fast先走到终点 //当链表长度为奇数时,fast->Next为空 //当链表长度为偶数时,fast为空 while( fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next; // 若有环则会从此处跳出while if(fast == slow) { break; } } // 判断出while循环是相遇而跳,还是快指针到尾结点了退出? if(fast == NULL || fast->next == NULL ) return false; else return true; }
(3)若单链表有环,环的长度?
答:第一次相遇点开始,两指针同时跑,开始计数。到第二次相遇时,慢指针跑了一圈,快指针跑了2圈,停止计数。计数值即为一圈长度。
int loopLength(pNode *pHead) { // 判断是否有环 if(isLoop(*pHead) == false) return 0; pNode *fast = pHead; pNode *slow = pHead; int length = 0; bool begin = false; bool agian = false; while( fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next; //第2次相遇,停止计数,出循环 if(fast == slow && agian == true) break; //第一次相遇,开始计数 if(fast == slow && agian == false) { begin = true; agian = true; } //计数 if(begin == true) ++length; } return length; }
(4)如何找到环的入口点?
答:由归纳推理可得,从第一次的相遇点处,到环入口的距离,等于头结点到环入口的距离。
假设头结点到入口处为L1,相遇点顺时针入口点为L3,入口点到相遇点为L2。则当两指针相遇时,慢指针走了(L1+L2),快指针速度是2倍,应该走的是2(L1+L2)。再根据图上关系,快指针走的还可以表示为(L1+L2+L3+L2),则
所以当第一次相遇时,从相遇点和头结点分别设置两个移动步长均为1的指针,当相遇时,相遇点即为入口点。
Node* findLoopEntrance(pNode *pHead) { pNode *fast = pHead; pNode *slow = pHead; while( fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next; //如果有环,则fast会超过slow一圈 if(fast == slow) { break; } } if(fast == NULL || fast->next == NULL) return NULL; slow = pHead; while(slow != fast) { slow = slow->next; fast = fast->next; } return slow; }
(5)如何判断两个链表(不带环)是否相交?
答:可将其中一个链表的尾指针指向头结点。从另一个链表查找是否有环。如果有环说明相交;没有环说明不相交。
参考资料
【1】http://blog.csdn.net/thefutureisour/article/details/8174313
- 剑指offer-15:单链表有趣问题-有环-环长度-环入口等(续)
- 【算法之链表(一)】判断单链表中是否有环、环的长度、环的入口节点,单链表的倒数第K个节点等
- Java单链表基本操作(十)--判断单链表是否有环并输出环长度以及环的入口节点
- 如何判断单链表是否有环、环的入口、环的长度和总长
- 剑指offer--判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 剑指offer面试题-判断链表是否带环并求环的入口点和环的长度
- 剑指offer 15---判断链表是否带环?若带环求环的长度?若带环求环的入口点?
- 判断一个单链表是否有环,如果有环求出环的入口点和环的长度
- 判断单链表中是否有环,环的长度,环的入口节点
- 如何判断是否有环,如何计算环的长度,如何判断环的入口点
- 【链表】判断链表是否有环,环的长度,环的入口点
- 判断单链表是否存在环及求环入口结点等问题
- java面试题(剑指Offer):找出该链表的环的入口结点
- 判断单链表是否有环及确定环的入口结点问题
- 判断单链表是否有环及确定环的入口结点问题
- 数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点
- 单链表是否有环并如何找到环入口
- 单链表是否有环并如何找到环入口
- 《C++ primer》第五版 练习7.32 报错:“error C2797: 'Window_mgr::screens': 未执行成员初始值列表内的列表初始化或非静态数据成员初始值”
- ES6 —(字符串扩展)
- 添加圆角效果
- Machine learning9----EM算法(十大经典算法)
- 二叉树的下一个节点
- 剑指offer-15:单链表有趣问题-有环-环长度-环入口等(续)
- rel6与rel7
- HDU 3183 A Magic Lamp 【RMQ 递归 求解】
- Linux notes, vim使用
- IntelliJ IDEA 常用快捷键
- .net mvc + vuejs 的项目结构
- Log4j2+Slf4j快速入门
- 5-51 两个有序链表序列的合并
- JAVA设计模式之单例模式