带环链表问题 查找带环链表的起始环节点

本文介绍了一个LintCode上的算法题目“带环链表II”的解决方案。该问题旨在判断链表是否包含环,并返回环的起始节点。文章详细阐述了如何通过双指针法确定环的存在及定位起始节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个问题是 LintCode 上面的一个算法题目( 带环链表 II ),主要考察的是对于链表,带环链表的理解。

原问题描述:

给定一个链表,如果链表中存在环,则返回到链表中环的起始节点,如果没有环,返回null。

样例:

给出 -21->10->4->5, tail connects to node index 1,返回10
分析:
这个问题的思路主要分为以下几步:
1.判断这个链表是不是带环链表
2.如果是带环链表,则返回环上的一个节点
3.从头节点开始,一步一步往后挪动,每次都判断节点是不是在环上面
判断方法: 使得环上的节点绕环一周,如果遇到了测试节点,则说明测试节点是环上面的一个节点

如果绕完一周以后,一直没有碰到测试节点,说明测试节点不是环上面的一个节点


解决代码:

public class TestDetectCycle {
	public ListNode detectCycle(ListNode head){
		//如果存在循环体,则链的下一个节点是不会为空的
		if (head == null || head.next == null) return null;
		//找到链上面的一个节点
		ListNode nodeInCycle = findANodeInCycle(head, head.next);
		//如果返回为空,则说明没有循环体
		if (nodeInCycle == null) return null;
		//将头结点和环上面任意节点传入,寻找起始点
		return findStart(head, nodeInCycle);
	}

	/**
	 * 在链表上的循环体内找到一个节点
	 * @param node1 每次跨度为  1  的节点
	 * @param node2	每次跨度为2的节点
	 * @return 返回的是循环体内的一个节点,如果没有循环体,则返回null
	 */
	private ListNode findANodeInCycle(ListNode node1, ListNode node2) {
		//只有任意一个节点为空,则说明没有循环体,返回null
		if (node1 == null || node2 == null) return null;
		//说明两个跨度不同的节点碰到了一起,那么此时此时节点就在循环体内
		if (node1 == node2) return node1;
		//这是为了防止下一行的代码报空指针异常
		//只要某一个节点的下一个节点为空,则说明没有循环体
		if (node2.next == null) return null;
		//通过移动不同的跨度,寻找循环体
		return findANodeInCycle(node1.next, node2.next.next);
	}

	/**
	 * 寻找循环体的起始节点
	 * @param node	头结点
	 * @param nodeInCycle	循环体上面的一个节点
	 * @return 返回其实节点
	 */
	private ListNode findStart(ListNode node, ListNode nodeInCycle) {
		while ( ! isStartNode(node, nodeInCycle)){
			//这个节点不是起始节点,则移动到下一节点,继续验证
			node = node.next;
		}
		return node;
	}

	private boolean isStartNode(ListNode node, ListNode nodeInCycle) {
		//为了让while循环体顺利进行,一开始不能让node2 == nodeInCycle,只要让node2往后挪动一步就行了
		ListNode node2 = nodeInCycle.next;
		//while代码段会让node2绕着循环体跑一圈,如果能遇到node,说明node就在循环体上
		//如果绕完一圈后,还是没有遇到node,说明node不在循环体上面
		while (node2 != nodeInCycle) {
			if (node == node2) return true;
			node2 = node2.next;
		}
		//因为当尾部节点指向其自身的话,while中的循环体是不会进去的,因为此时nodeInCycle == node2
		//这时只要判断test节点node是不是等于nodeInCycle就行了
		return node == node2;
	}
}
关于判断链表是否有环,更具体的请参考我的另一篇博客 带环链表
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值