1.判断单链表是否带环?
//判断是否带环 我们可以用快慢指针思想 我们来两个指针一个 一个每次走一步
//一个每次走两步 如果不带环那么它两走到最后是不会碰面的 反之 如果带环
//那么它们迟早会碰面
ListNode* HaveLoop(ListNode* phead)
{
if(pHead==NULL)
return NULL;
ListNode* fast=phead;
ListNode* slow=Phead;
while(fast&&fast->next){
fast=fast->next->next;
slow=slow->next;
if(slow==fast)
return slow;
}
return NUll;
}
2.如果链表带环求环的长度
//求换的长度 我们可以借助上面判断是否有环的返回值 你想想
//链表有环 两个指针相遇那么肯定是在环内相 遇 记录慢指针的为主 那么我们
//只需要来一个指针让它从慢指针走 然后再次回到慢指针的位置即可
int lengthloop(ListNode* phead)
{
ListNode* tmp=HaveLoop(phead);
int count=0;
if(tmp!=NULL){
ListNode* cur=tmp;
while(cur!=tmp)
{
cur=cur->next;
count++;
}
}
return count;
}
3.如果链表带环 那么求环的入口点
//思路还是一样滴 快慢指针 先让两个指针都走 然后记录它们的相遇点
//此时快指针从新重新指向头结点 然后让慢指针从相遇点 快指针从头结点
//一步一步走 那么它们再次相遇的点就是入口 (画图一幕了然)
ListNode* FindEntry(ListNode* pHead)
{
assert(pHead);
SListNode* fast = pHead;
SListNode*slow = pHead;
while (fast&&fast->next) //让快指针追上慢指针
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
break;
}
}
fast = pHead; //再让快指针指向头结点
while (fast != slow) //两指针都走一步,当两指针在此相遇时,就是入口点
{
fast = fast->next;
slow = slow->next;
}
return fast;
}
4.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
//思路一:我们先遍历到链表一到它的尾部 然后让它尾部指向链表二的头部
//此时如果两个链表没有相交的话那么它们会变成一个链表
//如果它们相交的话那就相当于一个链表里有了环
//所以连接后就变成了判断是否带环问题 交点就是环的入口
//思路二: 我们遍历两个链表 如果链表相加那么它们的最后一个结点必定是一样的
//如果相同,则相交;否则不相交。
//求交点可以这样搞 计算链表1与链表2的长度之差 然后让长链表先走差的绝对值步
//然后一起走 当结点相同时 就是交点
int length(ListNode* phead){
if(phead==NULL)
return 0;
int count=0;
ListNode* cur=phead;
while(cur!=NULL){
cur=cur->next;
count++;
}
return count;
}
ListNode* ISintersect(ListNode* phead1,ListNode* phead2){
if(phead1==NULL||phead2==NULL)
return NULL;
int len1=length(phead1);
int len2=length(phead2);
ListNode* long=NULL;
ListNode* short=NULL;
ListNode* p1=phead1;
ListNode* p2=phead2;
while(p1!=NULL){
p1=p1->next;
}
while(p2!=NULL)
{
p2=p2->next;
}
if(p1!=NULL)
return NULL;
int count=(len1-len2)<0?(-1)*(len1-len2):(len1-len2);
if(len1>len2){
long=phead1;
short=phead2;
} else{
long=phead2;
short=phead1;
}
while(count)
{
long=long->next;
count--;
}
while(long!=short){
long=long->next;
short=short->next;
}
return long;
}
5.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)
//这题我们可以先分情况捋一捋 第一种两个都不带换那么就按上一个题的方法解决
//第二种 一个带环 一个不带环 这种情况它们可定不想交 如果相交那么就变成
//两个链表都带环了
//第三种就是两个都带环了 这个又分两种 交点在环上 那么我们可以去掉环当成
//无环问题解决求交点 如果交点在环上 那么就有可能有两个交点 得把两个都找出来
ListNode* Istersect(ListNode* plist1, ListNode* plist2)
{
if(plist1==NULL||plist2==NULL)
return NULL;
ListNode* enter1 = HaveLoop(plist1);//判断是否有环
ListNode* enter2 = HaveLoop(plist2);
ListNode* node1=FindEntry(plist1);
ListNode* node2=FindEntry(plist2);
if ((enter1 == NULL) && (enter2 == NULL)) //第一种情况
{
return ISintersect(plist1, plist2);
}
else if ((enter1 == NULL) && (enter2 != NULL) || (enter1 != NULL) && (enter2 == NULL)) //第二种情况
{
return NULL;
}
else if (node1 == node2) //第三种 当只有一个入口点时 交点就只有一个
{
node1->next = NULL;
node2->next = NULL;
return ISintersect(plist1, plist2);
}
else //当有两个入口时
{
ListNode* tmp = node1->next;
while (tmp != node1)
{
if (tmp == node2)
{
return enter1;
}
tmp = tmp->next;
}
return NULL;
}