判断单链表是否带环

//这个题思路不难,我们只要定义两个指针,一快一慢,快指针一次走两步,慢指针一次走一步
//如果它们相遇,则单链表构成了环形结构。 如果未相遇, 而快指针走到了链表结尾,则单链表未构成环形结构
#include <iostream>
using namespace std;


struct ListNode{
	int m_nKey;
	ListNode* m_pNext;

	ListNode( ListNode* pNext, int value )
		: m_pNext( pNext )
		, m_nKey( value )
	{}
};


bool IsRing( ListNode* pListHead );
void push_back( ListNode** pHead, int value );
ListNode* Find( ListNode* pListHead, int value );


int main( )
{
	ListNode* pHead = NULL;
	//push_back( &pHead, 1 );
	//push_back( &pHead, 2 );
	//push_back( &pHead, 3 );
	//push_back( &pHead, 4 );
	//push_back( &pHead, 5 );	
	
	push_back( &pHead, 1 );
	push_back( &pHead, 2 );
	push_back( &pHead, 3 );
	push_back( &pHead, 4 );
	push_back( &pHead, 5 );

	ListNode* pNode3 = Find( pHead, 3 );
	ListNode* pNode5 = Find( pHead, 5 );

	pNode5->m_pNext = pNode3;

	cout << IsRing( pHead );

	return 0;
}


void push_back( ListNode** pHead, int value )
{
	if ( NULL == pHead )
		return;

	ListNode* pNewNode = new ListNode( NULL, value );

	if ( NULL == *pHead ){
		*pHead = pNewNode;
		return;
	}

	ListNode* pNode = *pHead;

	while ( NULL != pNode->m_pNext )
		pNode = pNode->m_pNext;

	pNode->m_pNext = pNewNode;
}

ListNode* Find( ListNode* pListHead, int value )
{
	if ( NULL == pListHead )
		return NULL;

	ListNode* pNode = pListHead;

	while ( NULL != pNode && value != pNode->m_nKey )
		pNode = pNode->m_pNext;

	if ( NULL == pNode )
		return NULL;

	return pNode;
}

//以后写代码,一定不要忘了考虑边界情况
bool IsRing( ListNode* pListHead )
{
	if ( NULL == pListHead )
		return false;

	ListNode* pFast= pListHead;
	ListNode* pSlow= pListHead;

	while ( NULL != pFast->m_pNext ){
		if ( NULL != pFast->m_pNext->m_pNext ){
			pFast = pFast->m_pNext->m_pNext;
			pSlow = pSlow->m_pNext;
		}
		else
			return false;

		if ( pSlow == pFast )
			return true;
	}

	return NULL;
}

判断单链表是否有环的方法有以下几种: #### 追及法(快慢指针法) 设置两个指针,一个是 `slow`,另一个是 `fast`。`slow` 一次走一个节点,`fast` 一次走两个节点,当 `fast` 追上 `slow` 即 `fast` 和 `slow` 重合时,说明链表中有环 [^4]。 以下是Python代码示例: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def hasCycle(head): slow = head fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: return True return False ``` #### 哈希法 维护一个哈希表,遍历链表将每个节点的地址存入哈希表中,如果出现重复就代表链表有环 [^4]。 以下是Python代码示例: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def hasCycle(head): visited = set() while head: if head in visited: return True visited.add(head) head = head.next return False ``` #### 标记法 遍历单链表,将经过的节点都做标记,采用的方法是将遍历的节点都放入集合 `visited` 中,对每个节点判定是否在集合中出现过,若出现重复访问,则判定有环。空间复杂度为 $O(n)$,时间复杂度为 $O(n^2)$ [^3]。 以下是Java代码示例: ```java import java.util.ArrayList; class Node { int val; Node next; Node(int x) { val = x; next = null; } } public class Main { private static boolean methodSecond(Node head) { ArrayList<Node> visited = new ArrayList<>(); while (head != null) { if (visited.contains(head)) { return true; } visited.add(head); head = head.next; } return false; } } ``` #### 链表合并转化法 先遍历第一个链表到它的尾部,然后将尾部的 `next` 指针指向第二个链表(尾部指针的 `next` 本来指向的是 `null`),这样两个链表就合成了一个链表,判断原来的两个链表是否相交也就转变成了判断新的链表是否有环的问题 [^1]。 #### 反转链表法 反转链表时,会用到3个指针,分别为指向遍历时当前的结点的 `current` 指针,指向反转后的子链表的头结点的指针 `temp`,及指向遍历时当前结点的下一个结点的 `next` 指针,如果在反转时,出现了 `next` 指向头结点的情况,那么肯定是有环的 [^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值