題目:
編程判斷兩個鏈表是否相交
解題思路:
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;
}
}