您的位置:首页 > Web前端

【剑指offer系列】 链表中倒数第k个节点___15

2016-04-08 10:15 686 查看
  题目描述:

  给定一个单链表的头节点,删除该链表的倒数第k个节点。(尾部节点为倒数第一个节点)

  

  示例:

  链表为:4–>3–>2–>1–>NULL,则倒数第一个节点为1,若k=3。

  则输出值为3的那个节点的指针

  

  分析:

  对于单链表的这种查找问题,一般都可以用快慢指针来解决。

  注意k <= 0和k > list.len两种情况返回NULL

  

  代码:     

listNode *findKthToTail(listNode *head,int k){
if(k<=0||head==NULL)    return NULL;

int len=0;
listNode *fast=head,*slow=head;
while(len<k&&fast){
fast=fast->next;
++len;
}
if(len<k)   return NULL;   //k > list.len

while(fast){
fast=fast->next;
slow=slow->next;
}
return slow;
}


  相关题目:

  1、返回单链表的中间节点。

  当节点数为奇数时,返回中间节点。当节点数为偶数时,返回中间节点中的任意一个

  

  分析:

  同样使用快慢指针,fast走两步,slow走一步。

  当fast到达链表尾部的NULL指针时,slow恰好指向中间节点

  

  代码:  

listNode *findMidNode(listNode *head){
if(head==NULL||head->next==NULL)   return head;
listNode *slow=head;
listNode *fast=head;
while(1){
fast=fast->next;
if(fast==NULL)   return slow;  //节点数为奇数的情况
slow=slow->next;
fast=fast->next;
if(fast==NULL)   return slow;  //节点数为偶数的情况
}
}


  2、判断单链表是否成环 (leetcode 141)

  

  分析:

  同样使用快慢指针,fast走两步,slow走一步。

  如果单链表有环,则fast和slow在到达尾部NULL节点之前,一定会相遇。

  否则fast一定会到达NULL节点

  

  代码:   

bool hasCycle(ListNode *head) {
ListNode *p=head;
if((p==NULL)||(p->next==NULL))  return false;
ListNode *q=head;
while(1){
if(q==NULL||q->next==NULL) return false;   //能到达NULL,一定无环
p=p->next;
q=q->next->next;
if(p==q)    return true;   //p、q能相遇,一定有环
}
}


  3、找到单链表中环的起始节点 (leetcode 142)

  如果无环,则返回NULL

  

  分析:

  


  slow和fast同时从head出发,如果链表有环,则二者一定会在环中相遇。

  假设二者在环中的 z 处相遇,则slow走过的路径长度为 S=a + b ,fast走过的路径长度为 F = a+ b + c +b =a + c + 2b

  而fast走过的长度为slow的两倍,因此 F = 2 S。即 a+b = b+c,因此 a = c

  此时让slow回到head处,然后slow和fast以后每次都只走一步

  二者再次相遇时,slow走了 a 步,fast走了 c 步,而 a = c,二者恰好在环的入口相遇

  

  代码:  

ListNode *detectCycle(ListNode *head) {
ListNode *p=head;
if(p==NULL||p->next==NULL)  return NULL;
ListNode *q=head;
while(1){
if(q==NULL||q->next==NULL) return NULL; //无环,返回NULL
p=p->next;
q=q->next->next;
if(p==q)         break;   //二者在 Z 处相遇
}
p=head;   //slow回到head处
while(1){
if(p==q)    return p;  //二者再次相遇
p=p->next;   //slow和fast以后每次都只走一步
q=q->next;
}
}


  如果要计算环的长度时,当fast和slow第一次相遇后,让二者继续走。

  当二者再次相遇时,slow走的长度为len,fast走的长度为2len,

  fast恰好比slow多走一圈,因此环的长度为 2len-len = len;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: