判斷兩個鏈表是否有公共節點

#include<iostream>
using namespace std;

struct ListNode
{
	int value;
	struct ListNode * next;
	ListNode(int v = 0) :value(v), next(nullptr){}
};

//判斷是否有環,如果有環,返回環內節點;如果沒有環,則返回nullptr
ListNode * IsLoop(ListNode * head)
{
	if (head == nullptr || head->next == nullptr)
		return nullptr;

	ListNode * slow = head;
	ListNode* fast = head->next;
	while (fast!=nullptr&&slow!=fast)
	{
		slow = slow->next;
		fast = fast->next;
		if (fast != nullptr)
		{
			fast = fast->next;
		}
	}
	return fast;
}

//計算環內長度
int LoopLenght(ListNode * head)
{
	ListNode * stop = head;
	head = head->next;
	int count = 1;
	while (head!=stop)
	{
		count++;
		head = head->next;
	}
	return count;
}
//獲得環的入口結點
ListNode* EntryLoop(ListNode * head,int length)
{
	if (head==nullptr || length==0)
	{
		return nullptr;
	}

	ListNode * slow=head;
	ListNode * fast = head;
	for (int i = 0; i <length; i++)
	{
		fast = fast->next;
	}

	while (slow!=fast)
	{
		slow = slow->next;
		fast = fast->next;
	}
	return fast;
}


//計算帶環,鏈表長度
int List_length(ListNode * head, ListNode * end,int loop)
{
	int count = 0;
	while (head!=end)
	{
		count++;
		head = head->next;
	}
	return count+loop;
}

ListNode * ListMeet(ListNode* head1, ListNode * head2, int len1, int len2)
{
	if (len1<len2)
	{
		swap(head1, head2);
	}

	int k = abs(len1 - len2);
	while (k--)
	{
		head1 = head1->next;

	}
	while (head1 != head2)//nullptr時相等
	{
		head1 = head1->next;
		head2 = head2->next;
	}
	return head1;
}

bool TwoListMeet(ListNode * head1, ListNode* head2)
{
	ListNode* isloop1= IsLoop(head1);
	ListNode* isloop2 = IsLoop(head2);


	//一個有環,一個無環,則必不存在交點
	if ((isloop1==nullptr)^(isloop2==nullptr))
	{
		return  false;
	}

	//兩個鏈表都沒有環
	if ((isloop1 == nullptr) &&(isloop2 == nullptr))
	{
		int len1 = List_length(head1, nullptr, 0);//計算不帶環鏈表長度
		int len2 = List_length(head2, nullptr, 0);
	
		if(ListMeet(head1,head2,len1,len2)==nullptr)//可以保存meet節點
			return false;
		else
			return true;
	}

	//兩個鏈表都有環時
	//環內長度
	int looplenght1=LoopLenght(isloop1);
	int looplenght2 = LoopLenght(isloop2);


	//獲得環的入口結點
	ListNode* entry1 = EntryLoop(head1, looplenght1);
	ListNode* entry2 = EntryLoop(head2, looplenght2);

	//環外相遇
	if (entry1==entry2)
	{

		//尋找相遇結點
		int listlenght1 = List_length(head1, entry1, looplenght1);//計算帶環鏈表長度
		int listlenght2 = List_length(head2, entry2, looplenght2);

		ListNode* meet=ListMeet(head1, head2, listlenght1, listlenght2);//計算相遇節點
		return true;
	}
	else
	{
		//判斷是否在環內相遇
		ListNode * temp = entry1;
		temp = temp->next;
		while (temp!=entry1&&temp!=entry2)
		{
			temp = temp->next;
		}

		if (temp == entry2)
			return true;
		else
			return false;
	}

	return false;
}


int main()
{
	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);
	ListNode * node7 = new ListNode(7);
	
	node1->next = node2;
	node2->next = node3;
	node3->next = node4;
	node4->next = node1;
	node5->next = node6;
	node6->next = node4;
	node7->next = node6;
	
	bool flag=TwoListMeet(node5, node7);
	return 0;

}

代碼中如有不妥,歡迎指出!!

測試鏈表樣列:

樣列1:

樣列2:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章