【Offer】[23] 【链表中环的入口结点】
题目描述
一个链表中包含环,如何找出环的入口结点?

思路分析
- 判断链表中是否有环:用快慢指针的方法,慢指针走一步,快指针走两步,如果快指针追上了慢指针,就说明有环,而且他们相遇的节点是处于环中的节点
- 统计环中节点的个数:利用1中返回的节点,当再次走到该节点时,正好遍历了整个环,从而可以统计出个数n。
- 找出入口结点:也是设置两个指针,第一个指针先向后移动n,第二个指针指向头节点,然后同时移动两个指针,它们相遇时的节点就是环的入口节点,(类似于 【链表中倒数第k个结点】 中的思路)
测试用例
- 功能测试:链表中包含或者不包含环;链表中有多个或者只有一
节点。 - 特殊输入测试:链表头节点为nullptr指针。
Java代码
public class Offer23 {
public static void main(String[] args) {
test1();
test2();
test3();
test4();
test5();
}
public static ListNode EntryNodeOfLoop(ListNode head) {
return Solution1(head);
}
/**
* 1.判断链表中是否有环,并找出环中节点个数n 2.将一个指针向前移动n,另个一指针指向头节点 3. 然后同时移动两个指针,两个指针相遇时,就是环的入口
*
* @param head
* @return
*/
private static ListNode Solution1(ListNode head) {
if (head == null) {
return null;
}
// 判断链表中是否有环,并找到快慢指针相遇的节点
ListNode meetNode = MeetingNode(head);
if (meetNode == null) {// 说明链表中没有环
return null;
}
int count = 1; // 统计环中节点的个数
ListNode pLoop = meetNode;
while (pLoop.next != meetNode) {
pLoop = pLoop.next;
++count;
}
ListNode p1 = head;
for (int i = 0; i < count; i++) {
p1 = p1.next;
}
ListNode p2 = head;
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
/**
* 设置两个指针,快指针一次走两步,慢指针一次走一步 如果快指针 追上了慢指针,就说明有环
* 如果快指针走到尾部(null)时两个指针没有相遇,就说明两个指针没有环存在,
*
* @param head
* @return
*/
private static ListNode MeetingNode(ListNode head) {
if (head == null) {
return null;
}
ListNode pSlow = head.next;
if (pSlow == null) {
return null;
}
ListNode pFast = pSlow.next;
while (pSlow != null && pFast != null) {
if (pSlow == pFast) {
return pFast;
}
pSlow = pSlow.next;
pFast = pFast.next;
if (pFast != null) {
pFast = pFast.next;
}
}
return null;
}
private static void test1() {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node3;
System.out.println("链表中有环而且有多个节点(>=3)---->");
ListNode entryLoop = EntryNodeOfLoop(node1);
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
private static void test2() {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
ListNode node6 = new ListNode(6);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
System.out.println("链表中没有环---->");
ListNode entryLoop = EntryNodeOfLoop(node1);
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
private static void test3() {
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
node1.next = node2;
node2.next = node1;
ListNode entryLoop = EntryNodeOfLoop(node1);
System.out.println("链表中有环,只有有两个个节点---->");
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
private static void test4() {
ListNode node1 = new ListNode(1);
node1.next = node1;
ListNode entryLoop = EntryNodeOfLoop(node1);
System.out.println("链表中有环,只有一个节点---->");
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("没有环");
}
}
private static void test5() {
ListNode entryLoop = EntryNodeOfLoop(null);
System.out.println("传入null---->");
if (entryLoop != null) {
System.out.println(entryLoop.val);
} else {
System.out.println("null");
}
}
}
代码链接
【Offer】[23] 【链表中环的入口结点】的更多相关文章
- 【Java】 剑指offer(23) 链表中环的入口结点
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中, ...
- 【剑指Offer】链表中环的入口结点 解题报告(Python)
[剑指Offer]链表中环的入口结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews ...
- 剑指offer:链表中环的入口结点
题目描述: 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 思路分析: 这道题首先需要判断链表是否存在环,很快就能想到用快慢指针来判断. 由于快慢指针的相遇位置并不一定为链 ...
- Go语言实现:【剑指offer】链表中环的入口结点
该题目来源于牛客网<剑指offer>专题. 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. Go语言实现: /** * Definition for sing ...
- 剑指Offer 55. 链表中环的入口结点 (链表)
题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 题目地址 https://www.nowcoder.com/practice/253d2c59ec3e4bc68d ...
- [剑指Offer] 55.链表中环的入口结点
题目描述 一个链表中包含环,请找出该链表的环的入口结点. [思路]根据set集合的不重复,遍历链表时遇到的第一个重复结点就是环的入口结点. /* struct ListNode { int val; ...
- 剑指Offer:链表中环的入口节点【23】
剑指Offer:链表中环的入口节点[23] 题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 题目分析 第一步确定链表中是否包含环,怎么确定呢?我们定义两个指针橙和 ...
- 《剑指offer》第二十三题(链表中环的入口结点)
// 面试题23:链表中环的入口结点 // 题目:一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中, // 环的入口结点是结点3. #include <iostream> ...
- 链表中环的入口结点 牛客网 剑指Offer
链表中环的入口结点 牛客网 剑指Offer 题目描述 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. # class ListNode: # def __init__(se ...
- 【剑指offer】面试题 23. 链表中环的入口节点
面试题 23. 链表中环的入口节点
随机推荐
- 浅谈单例模式及其java实现
单例模式是23种设计模式中比较简单的一种,在此聊一下单例模式. 1.什么是设计模式? 对于没有接触过设计模式的人来说,一听到设计模式这四个字就觉得这个东西很高深莫测,一下子就对这个东西产生了恐惧感,其 ...
- SpringBoot配置web访问H2
[**前情提要**]最近开始搭建博客,在本地调试的时候使用的数据库是h2,但是调试的时候需要查看数据库,本文也由此而来. --- 下面是我用到的方法: 1. 使用IDEA的Database连接工具,具 ...
- Zookeeeper环境搭建(二)
zk一般是有2n+1个节点组成的集群.在Zookeeper服务有两个角色,一个是leader,负责写服务和数据同步:剩下的是follower,提供读服务.(为什么是2n+1个节点请看paxos算法) ...
- C++基础之:扫雷破解
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- Kafka面试,看这篇文章就够了
原文链接:https://mp.weixin.qq.com/s/zxPz_aFEMrshApZQ727h4g** 引言 MQ(消息队列)是跨进程通信的方式之一,可理解为异步rpc,上游系统对调用结果的 ...
- Linux系统关机与重新引导流程简介
引言 在<Linux启动之旅>中,我们了解了Linux的启动过程,下面我们一同来学习Linux关机与重新引导流程. 不同于桌面系统,作为服务器,我们较少对Linux系统进行系统重启,但在以 ...
- Linux文件及目录管理
1.Linux文件目录树 /:根目录,linux文件系统的最顶端和入口 bin:存放用户二进制文件(如:ls,cd,mv等),实则/user/bin的硬链接(相当于Windows系统的快捷方式) bo ...
- intellij idea与github整合管理代码
各位看官大家好,博主每每在公司学习新知识写代码时都需要通过U盘带回家来继续每天的学习,觉得这样实在麻烦,于是今天就整合了一下github来完成代码的管理. 开始之前我们需要准备三样东西:1.intel ...
- 为何Spring MVC可获取到方法参数名,而MyBatis却不行?【享学Spring MVC】
每篇一句 胡适:多谈些问题,少聊些主义 前言 Spring MVC和MyBatis作为当下最为流行的两个框架,大家平时开发中都在用.如果你往深了一步去思考,你应该会有这样的疑问: 在使用Spring ...
- 天天都用消息队列,却不知道为啥要用MQ,这就有点尴尬了
1.为什么要使用消息队列? 分析:一个用消息队列的人,不知道为啥用,有点尴尬.没有复习这点,很容易被问蒙,然后就开始胡扯了. 回答:这个问题,咱只答三个最主要的应用场景(不可否认还有其他的,但是只答三 ...