题目:
编程判断两个链表是否相交
解题思路:
1 直接循环判断第一个链表中节点是否在第二个链表中(时间复杂度为O(size(listOne) * O(size(listTwo))
2 针对第一个链表构造hash表,判断第二个链表中节点是否在hash表中(时间复杂度为O(size(listOne) + O(size(listTwo),空间复杂度为O(size(listOne))
3 思路与2相同,只是用链表长度较短的一个构造hash表,这样空间复杂度能低一点
4 如果两个链表相交与某节点,在这个节点之后的所有节点都是两个链表的共有节点,所以只需找到两个链表最后的一个节点,判断是否相等即可(时间复杂度为O(size(listOne) + O(size(listTwo))
5 若两个链表中有环,设置两个指针fast,slow,slow每次前进一步,fast每次前进两步,若链表有环,则fast与slow必定在某个时刻相等
1) 两个链表中都有环,判断第一个链表中fast与slow相交位置的节点是否在第二个链表中,若在则相交
2) 两个链表一个有环,一个无环,则两个链表不想交
3) 两个链表都无环,判断两个链表中最后一个节点是否相等,若相等,则相交,否则不想交
总之,要判断两个链表(不知是否有环)是否相交,第一步判断两个链表是否有环,然后按照解题思路5操作
算法实现:
#include <iostream>
#include <string>
using namespace std;
struct Node
{
int value;
Node* next;
};
bool IsCircle(Node *head, Node ** circleNode, Node ** lastNode)
{
//若链表为空,返回false
if (nullptr == head)
{
circleNode = nullptr;
lastNode = nullptr;
return false;
}
Node* fast = head;
Node *slow = head;
while (fast != slow && nullptr != fast && nullptr != slow)
{
//fast多走一步
if (nullptr != fast->next)
{
fast = fast->next;
}
//若链表无环,fast先找到链表最后一个节点,此时*lastNode = fast
if (nullptr == fast->next)
{
*lastNode = fast;
}
slow = slow->next;
fast = fast->next;
}
if (fast == slow && nullptr != fast)
{
*circleNode = fast;
return true;
}
else
{
return false;
}
}
bool TwoListIsIntersect(Node *listOne, Node *listTwo)
{
if (nullptr == listOne || nullptr == listTwo)
{
return false;
}
Node *circleNodeOne = nullptr;
Node *circleNodeTwo = nullptr;
Node *lastNodeOne = nullptr;
Node *lastNodeTwo = nullptr;
bool isCircleOne = IsCircle(listOne, &circleNodeOne, &lastNodeOne);
bool isCircleTwo = IsCircle(listTwo, &circleNodeTwo, &lastNodeTwo);
//两个链表一个有环,一个无环,则不想交
if (isCircleOne != isCircleTwo)
{
return false;
}
else if (!isCircleOne && !isCircleTwo && nullptr != lastNodeOne)//两个链表都无环
{
return lastNodeOne == lastNodeTwo;
}
else//两个链表都有环
{
Node *temp = circleNodeOne;
do
{
if (temp == circleNodeTwo)
{
return true;
}
} while (temp != circleNodeOne);
return false;
}
}