# 单链表面试题总结（二）

1.输出链表中倒数第k个节点

ListNode* FindKtoTail(ListNode * phead,unsigned int k)
{
if(phead == NULL || k == 0)//(1)整个链表为NULL，(2)k不能为0，k时无符号整数，k-1是一个非常大的无符号整数，要不停循环
return NULL;
ListNode * pslow = NULL;//这里第一次置空，不要忘了
for(unsigned int i=0;i <k-1;++i)
{
if(pfast->pnext != NULL)//如果k大于链表节点数，会导致pfast越界，这里要判断
{
pfast = pfast->pnext;
}
else  //如果k大于链表节点数，直接return
{
return NULL;
}
}

while(pfast->pnext != NULL)
{
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return pslow;
}

2.删除链表第k个节点 方法同上，快慢指针

{
if(phead == NULL || k == 0) return false;
ListNode* pslow = NULL;
for(int i=0;i<k-1;++i)
{
if(pfast->pnext != NULL)
{
pfast = pfast->pnext;
}
else
{
return false;
}
}
while(pfast->pnext != NULL)
{
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return true;

}

3.求链表的中间节点 方法和上面差不多，快慢指针

{
while(pfast->pnext != NULL)
{
pfast = pfast->pnext;
if(pfast->pnext != NULL)
{
pfast = pfast->pnext;
}
pslow = pslow->pnext;
}
return pslow;

}

4.判断链表是否有环

{
while(pfast->pnext != NULL)
{
pfast = pfast->pnext;
if(pfast->pnext != NULL)//快指针走两步
{
pfast = pfast->pnext;
}
pslow = pslow->pnext;//慢指针走一步
if(pfast == pslow)//快慢指针碰面，说明有环
{
return pslow;
}
}
return NULL;
}

5.求环的入口地址

{
if(pslow == NULL) return NULL;//没环
while(pfast != pslow)//相遇则跳出
{
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return pslow;//相遇点即入口地址，返回
}

6.求环的长度，直接把判断是否有环的代码调用一下，然后计算长度

{
if(pmeet == NULL) return 0;
ListNode *pslow = pmeet->pnext;
int count = 1;//从相遇点的下一个节点开始走，所以把count初始化为1
while(pslow != pmeet)
{
pslow = pslow->pnext;
count++;
}
return count;
}

7.判断两个链表是否相交，返回第一个交点
【如果两个单链表有交点，那么从交点开始，它们的pnext都指向同一个节点，不可能再分叉】

{
int len1 = 0;
int len2 = 0;
int len = 0;
for(;p1 != NULL;p1 = p1->pnext)
len1++;
for(;p2 != NULL;p2 = p2->pnext)
len2++;
ListNode* pslow = NULL;
if(len1 > len2)//分情况计算长度之差
{
len = len1-len2;
}
else
{
len = len2-len1;
}
for(int i=0;i<len;++i)//快指针先走len步
pfast = pfast->pnext;
while(pfast != pslow)//快慢指针同时走
{
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return pslow;

}

8.合并两个有序链表
(1)用递归合并

{
ListNode* pmerge = NULL;
{
}
{
}
return pmerge;
}

(2)不用递归 合并两个有序链表

{
ListNode* plist = (ListNode*)malloc(sizeof(ListNode));//新链表头节点，一会要返回
while(p1 != NULL && p2 != NULL)   合并也需要合并最后一个节点，所以要走到最后
{
if(p1->mval < p2->mval)
{
p1 = p1->pnext;
}
else
{
p2 = p2->pnext;