1、判断两个链表是否相交,若相交,求交点。(假设链表可能带环)。
#include<iostream>
#include<assert.h>
using namespace std;
struct ListNode
{
int _value;
ListNode* _next;
ListNode(int value)
:_value(value)
, _next(NULL)
{}
};
ListNode* IsCircleList(ListNode* pHead)//是否带环,返回快慢节点相交的节点
{
if (pHead == NULL)
return NULL;
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
while (pFast && pFast->_next)
{
pFast = pFast->_next->_next;
pSlow = pSlow->_next;
if (pFast == pSlow)
return pSlow;
}
return NULL;
}
int Size(ListNode* pHead)
{
ListNode* pLast = pHead;
int count = 1;
while (pLast->_next)
{
count++;
pLast = pLast->_next;
}
return count;
}
bool IsCrossList(ListNode* pHead1, ListNode* pHead2)//判断两个链表是否相交
{
if (pHead1 == NULL || pHead2 == NULL)
return true;
ListNode* pCur1 = pHead1;
ListNode* pCur2 = pHead2;
while (pCur1->_next)
pCur1 = pCur1->_next;
while (pCur2->_next)
pCur2 = pCur2->_next;
if (pCur1 == pCur2)
return true;
return false;
}
ListNode* CrossNode(ListNode* pHead)//判断入环节点
{
if (pHead == NULL)
return NULL;
ListNode* pNode = pHead;
ListNode* pMeet = IsCircleList(pHead);
if (pMeet == NULL)//链表不带环
return NULL;
//链表带环
while (pNode != pMeet)
{
pNode = pNode->_next;
pMeet = pMeet->_next;
}
return pNode;
}
//判断两个链表的相交点,两个带环
int Number(ListNode* pHead, ListNode* pNode)
{
if (pHead == NULL || pNode == NULL)
return 0;
ListNode* pCurNode = pHead;
int count = 1;
while (pCurNode != pNode)
{
count++;
pCurNode = pCurNode->_next;
}
return count;
}
ListNode* CircleListNode(ListNode* pHead1, ListNode* pHead2)//判断两个链表的相交点,两个带环
{
if (pHead1 == NULL && pHead2 == NULL)
return NULL;
ListNode* pCircleNode1 = IsCircleList(pHead1);//链表1环的节点
ListNode* pCircleNode2 = IsCircleList(pHead2);//链表2环的节点
if (pCircleNode1 == NULL && pCircleNode2 == NULL)//两个链表都不带环
{
if (IsCrossList(pHead1, pHead2))//两个链表相交
{
int count = Size(pHead1) - Size(pHead2);
ListNode* pStrNode = pHead1;
ListNode* pStyNode = pHead2;
if (count > 0)
{
while (count--)
pStrNode = pStrNode->_next;
}
else
{
count = 0 - count;
while (count--)
pStyNode = pStyNode->_next;
}
while (pStrNode != pStyNode)
{
pStrNode = pStrNode->_next;
pStyNode = pStyNode->_next;
}
return pStrNode;
}
else
return NULL;
}
//两个链表都带环
else if (pCircleNode1 && pCircleNode2)
{
ListNode* pCrossNode1 = CrossNode(pHead1);//链表1的入环节点
ListNode* pCrossNode2 = CrossNode(pHead2); //链表2的入环节点
ListNode* pCtrNode = pHead1;
ListNode* pCtyNode = pHead2;
if (pCrossNode1 == pCrossNode2)//两个链表从一个节点入环,则相交在这个节点之前或者这个节点
{
int number = Number(pHead1, pCrossNode1) - Number(pHead2, pCrossNode2);
if (number > 0)
{
while (number--)
pCtrNode = pCtrNode->_next;
}
else
{
number = 0 - number;
while (number--)
pCtyNode = pCtyNode->_next;
}
while (pCtrNode != pCtyNode)
{
pCtrNode = pCtrNode->_next;
pCtyNode = pCtyNode->_next;
}
return pCtrNode;
}
//相交点在环内,在一个环内找一个点,在另一个环内找到就有相交点,没找到就没相交点
ListNode *pCurNode = pCircleNode1;
while (pCircleNode1 != pCurNode->_next)//最后一个节点没遍历
{
if (pCurNode == pCircleNode2)
return pCurNode;
pCurNode = pCurNode->_next;
}
if (pCircleNode2 == pCurNode)
return pCurNode;
}
//一个带环,一个不带环永远不可能相交
return NULL;
}
void printfList(ListNode* pHead)
{
while (pHead)
{
cout << pHead->_value << " ";
pHead = pHead->_next;
}
cout << endl;
}
void Funtest()
{
ListNode* pHead1 = new ListNode(1);
ListNode* pNode = pHead1;
for (int idx = 3; idx <= 20; idx += 2)
{
pNode->_next = new ListNode(idx);
pNode = pNode->_next;
}
printfList(pHead1);
ListNode* pHead2 = new ListNode(2);
ListNode* pTemp = pHead2;
for (int idx = 4; idx <= 20; idx += 2)
{
pTemp->_next = new ListNode(idx);
pTemp = pTemp->_next;
}
printfList(pHead2);
//pTemp->_next = pHead1->_next;
//判断两个链表是相交
cout << "链表是否相交:" << IsCrossList(pHead1, pHead2) << endl;
//*****************************************************************
//判断链表是否带环
pNode->_next = pHead1->_next->_next->_next;
ListNode* pCircle1 = IsCircleList(pHead1);
//判断带环链表的快慢指针相交点
if (pCircle1)
cout << "链表1带环相交节点:" << pCircle1->_value << endl;
else
cout << "链表1不带环!" << endl;
//pTemp->_next = pHead2->_next->_next;
pTemp->_next = pHead1->_next->_next->_next->_next;
ListNode* pCircle2 = IsCircleList(pHead2);
if (pCircle2)
cout << "链表2带环相交节点:" << pCircle2->_value << endl;
else
cout << "链表2不带环!" << endl;
//找出链表带环的入环节点
ListNode* pCross1 = CrossNode(pHead1);
if (pCross1)
cout <<"链表1入环节点:"<<pCross1->_value << endl;
else
cout << "链表1不带环!" << endl;
ListNode* pCross2 = CrossNode(pHead2);
if (pCross2)
cout << "链表2入环节点:" << pCross2->_value << endl;
else
cout << "链表2不带环!" << endl;
//判断两个带坏链表的相交点
ListNode* pCircleNode = CircleListNode(pHead1, pHead2);
if (pCircleNode)
cout << "相交点:" << pCircleNode->_value << endl;
else
cout << "链表不相交!" << endl;
}