1.判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?
1)鏈表是否帶環,我們需要用快(走兩步)慢(走一步)指針,如果慢的和快的相等則鏈表帶環
bool ListCycl(Node* pHead)
{
if (pHead == NULL)
{
return fase;
}
Node* fast = pHead;
Node* slow = pHead;
while (fast)
{
fast = fast->next->next;
slow = slow->next;
if (slow == fast)
{
return true;
}
}
return false;
}
2)入口點
2.判斷兩個鏈表是否相交,若相交,求交點。(假設鏈表不帶環)
int Check_Link(ListNode* pList1,ListNode* pList2)
{
//判斷鏈表是否相交,查看其尾節點是否相同
ListNode* p1=pList1;
ListNode* p2=pList2;
if(p1==NULL||p2==NULL)
return -1;
while(p1->_next!=NULL)
{
p1=p1->_next;
}
while(p2->_next!=NULL)
{
p2=p2->_next;
}
if(p1==p2)
{
return 1; //相交
}
return 0;
}
ListNode* GetLinkNode(ListNode* pList1,ListNode* pList2)
{
//統計出兩個鏈表的結點總數count1,count2
//讓較長的鏈表走count1-count2步
//兩個鏈表一起走直到相遇則返回相遇結點的地址
int cout1=0;
int cout2=0;
assert(pList1);
assert(pList2);
ListNode* p1=pList1;
ListNode* p2=pList2;
while(p1)
{
cout1+=1;
p1=p1->_next;
}
while(p2)
{
cout2+=1;
p2=p2->_next;
}
p1=pList1;
p2=pList2;
int num=cout1-cout2;
if(num>0)
{
while(num--)
{
p1=p1->_next;
}
if(p1!=p2)
{
p1=p1->_next;
p2=p2->_next;
}
}
else
{
while(num--)
{
p2=p2->_next;
}
if(p1!=p2)
{
p1=p1->_next;
p2=p2->_next;
}
}
return p1;
}
3.判斷兩個鏈表是否相交,若相交,求交點。【升級版】 (假設鏈表可能帶環)
第一步,找環中相匯點。分別用slow,fast指向鏈表頭部,slow每次走一步,fast每次走二步,直到slow==fast找到在環中的相匯點。 第二步,找環的入口。接上步,當slow==fast時,fast所經過節點數爲2x,slow所經過節點數爲x,設環中有n個節點,fast比slow多走一圈有2x=n+x; n=x;可以看出slow實際走了一個環的步數,再讓fast指向鏈表頭部,slow位置不變,slow,fast每次走一步直到slow==fast; 此時slow指向環的入口。
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* fast=pHead;
ListNode* slow=pHead;
while(fast!=NULL && fast->next!=NULL)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)
break;
}
if(fast==NULL || fast->next==NULL)
return NULL;
fast=pHead;
while(slow!=fast)
{
slow=slow->next;
fast=fast->next;
}
return fast;
}
4.複雜鏈表的複製。一個鏈表的每個節點,有一個指向next指針指向下一個節點,還有一個random指針指向這個鏈表中的一個隨機節點或者NULL,現在要求實現複製這個鏈表,返回複製後的新鏈表。
//ps: 複雜鏈表的結構struct ComplexNode
{
int _data ; // 數據
struct ComplexNode * _next; // 指向下一個節點的指針
struct ComplexNode * _random; // 指向隨機節點(可以是鏈表中的任意節點 or 空)
};
第一步:複製所有鏈表的節點(設置next)
第二步:設置鏈表random指針。使用哈希表,將<N,N'>的對應關係
存到哈希表中,當設置時在O(1)時間就可以找到
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(pHead==NULL)
return NULL;
//定義一個哈希表
unordered_multimap<RandomListNode*,RandomListNode*> table;
// 開闢一個頭結點
RandomListNode* pClonedHead=new RandomListNode(pHead->label);
pClonedHead->next=NULL;
pClonedHead->random=NULL;
// 將頭結點放入map中
table.insert(make_pair(pHead,pClonedHead));
//設置操作指針
RandomListNode* pNode=pHead->next;
RandomListNode* pClonedNode=pClonedHead;
// 第一遍先將簡單鏈表複製一下
while(pNode!=NULL)
{
// 不斷開闢pNode的拷貝結點
RandomListNode* pClonedTail=new RandomListNode(pNode->label);
pClonedTail->next=NULL;
pClonedTail->random=NULL;
//連接新節點,更新當前節點
pClonedNode->next=pClonedTail;
pClonedNode=pCloneNode->next;//pNode比pClonedNode快了一個,所以要next之後再插入table
//將對應關係 插入到哈希表中
table.insert(make_pair(pNode,pClonedTail));//
//向後移動操作節點
pNode=pNode->next;
}
//需從頭開始設置random節點,設置操作指針
pNode=pHead;
pClonedNode=pClonedHead;
// 根據map中保存的數據,找到對應的節點
while(pNode!=NULL)
{
if(pNode->random!=NULL)
{
//找到對應節點,更新複製鏈表
pClonedNode->random=table.find(pNode->random)->second;
}
//向後移動操作節點
pNode=pNode->next;
pClonedNode=pClonedNode->next;
}
return pClonedHead;
}
};