解题:
快慢指针法:
快指针和慢指针从头结点开始走,快指针每次走两步,慢指针每次走一步,若不带环,快指针和慢指针不会相遇,若带环,快指针先进入环的入口点,当慢指针也进入环的入口点后,快慢指针将相遇。
1).判断单链表是否带环
ListNode *IsCycle(ListNode *list)//判断链表是否带环
{
ListNode *fast=list;
ListNode *slow=list;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
{
return slow;
}
}
return NULL;
}
2).若带环求环的长度
int GetCyclelen(ListNode* pList) //若带环求环的长度
{
ListNode* fast = pList;
ListNode* slow = pList;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
break;
}
if (fast != slow || fast->next == NULL)
return -1;
else
{
int count = 0;
do{
fast = fast->next->next;
slow = slow->next;
count++;
} while (fast != slow);
return count;
}
}
3).求环的入口点
思路:
1.同求环长,快慢指针相遇停止。
2.此时,将路程分为三段,一是 T——尾长(非环长度),二是 S——慢指针入环到被追上,三是 C——快指针追慢指针多跑的圈。那么,慢指针走的路程为 T+S,快指针走的路程为 T+S+C,可得 2(T+S)=T+S+C,T=C-S,此时,一个指针从起点出发走 T步,一个指针从快慢指针相遇点出发走 C-S 步,此时两指针刚好都在入口点。
3.两指针一个从头结点出发,一个从快慢指针相遇点出发,一步一步走,相遇的节点即为入口点(走的步数即为尾长 T(C-S))。
ListNode* GetCycleEnrty(ListNode* pList)
{
ListNode* fast = pList;
ListNode* slow = pList;
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
break;
}
if (fast != slow || fast->next == NULL)
return NULL;
while (pList != slow)
{
pList = pList->next;
slow = slow->next;
}
return pList;
}
1.若无环链表相交,则尾节点相同(长这样 >— ),新建指针遍历两链表,并统计步数(求交点用)。
2.尾节点不同,返回 NULL。
3.比较两链表长度,快指针从长链表头结点开始,走比短链表长的节点数。
4.慢指针从另一链表头结点开始,与快指针一起一步一步走,指针相同时停止。返回任意一个指针
ListNode* intersect1(ListNode* pList1, ListNode* pList2)//链表不带环相交求交点
{
int count1 = 0, count2 = 0;
ListNode* p1 = pList1, *p2 = pList2;
while (p1->next)
{
count1++;
p1 = p1->next;
}
while (p2->next)
{
count2++;
p2 = p2->next;
}
if (p1 != p2)return NULL;
if (count1 >= count2)
{
count1 -= count2;
while (count1--)
pList1 = pList1->next;
while (pList1 != pList2)
{
pList1 = pList1->next;
pList2 = pList2->next;
}
return pList1;
}
else
{
count2 -= count1;
while (count2--)
pList2 = pList2->next;
while (pList1 != pList2)
{
pList1 = pList1->next;
pList2 = pList2->next;
}
return pList1;
}
}
ListNode *IntersectRing(ListNode *list, ListNode *plist)
//判断两个链表是否相交,若相交,求交点。
//(假设链表可能带环)【升级版】
{
ListNode* oep1 = OepRing(list);
ListNode* oep2 = OepRing(plist);
//两个链表都不带环(也就是上一题的解决方案)
if ((oep1 == NULL) && (oep2 == NULL))
{
return Intersect(list, plist);
}
//一个带环,一个不带环(不可能相交)
else if (((oep1 == NULL) && oep2) || ((oep2 == NULL) && oep1))
{
return NULL;
}
//两个都带环
else
{
//尾交(一个交点,一个入口点)
//若两个链表的入口点一样则只有一个交点(交点也是入口点)
//两链表各自环入口点已经求出,把list的环从入口点断开
//可以转换成求不带环的相交链表求交点
if (oep1 == oep2)
{
oep1->next = NULL;
return Intersect(list, plist);//交点
}
else
{
//环交
//环交会有两个入口点,从一个入口点出发遍历环
//遍历的过程中有结点等于另一个入口点,则表示环交,返回指向那个结点的指针(就是交点)
//有两个交点,交点也是入口点。
//否则,就是两个带环链表不相交
//在这里返回的是第二个链表的入口点
//也是第一个链表在第二个链表中的交点
ListNode* cur = oep1->next;
while (cur != oep1)
{
if (cur == oep2)
{
return oep1;
}
cur = cur->next;
}
/*//在这里返回的是第一个链表的入口点
//也是第二个链表在第一个链表中的交点
ListNode* cur = oep2->next;
while (cur != oep2)
{
if (cur == oep1)
{
return oep2;
}
cur = cur->next;
}*/
return NULL; //不相交
}
}
}
//ps: 复杂链表的结构
struct ComplexNode
{
int _data ; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
};
分析:首先,复杂链表的复制,每个节点有两个指针next和指针random,复制的时候要将两个指针的信息全部复制上,因此我们可以一个指针一个指针依次复制。
具体思路:
void NewBackPrime(ComplexNode *list)
{
ComplexNode *cur=list;
while(cur)
{
ComplexNode *head=Init(cur->_data);
head->_next=cur->_next;
head->_random=NULL;
cur->_next=head;
cur=head->_next;
}
}
void ComplexNodeRandom(ComplexNode *list)
//第二步,复制随机结点
{
ComplexNode *cur = list;
while (cur)
{
//找到插入的新结点
ComplexNode *head = cur->_next;
//让新结点指向的随机结点
//去指向
//原先结点指向随机结点的后一个
if (cur->_random)
{
head->_random = cur->_random->_next;
}
cur = head->_next;
}
}
ComplexNode *RemoveNewCode(ComplexNode *list)
//第三步,让新创建链表的结点链接起来,原先链表的结点链接起来
{
ComplexNode *cur = list;
ComplexNode *head = NULL;
ComplexNode *tmp = NULL;
if (cur)
{
head = tmp = cur->_next;
cur->_next = tmp->_next;
cur = cur->_next;
}
while (cur)
{
//让新创建链表的结点链接起来
tmp->_next = cur->_next;
tmp = tmp->_next;
//原先链表的结点链接起来
cur->_next = tmp->_next;
cur = cur->_next;
}
return head;
}
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。