直接上代码,希望大家喜欢。`
//输入一个链表,输出该链表中倒数第k个结点。
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int data;
struct Node* next;
}Link;
Link *createLink(int a[])
{
Link *head;
Link *tail,*p;
head=NULL;
for(int i=0;i<6;i++)
{
p=(Link*)malloc(sizeof(Link));
p->data=a[i];
p->next=NULL;
if(!head) head=tail=p;
else
{
tail=tail->next=p;
}
}
return head;
}
/*
可行但不高效的常规解法:假设整个链表有n个结点,那么倒数第k个结点就是从头结点开始的第n-k+1个结点。
如果我们能够得到链表中结点的个数n,那我们只要从头结点开始往后走n-k+1步就可以了。那么,
这里的重点就在于如何求链表中节点的个数n,只需要从头开始遍历链表,每经过一个结点,计数器加1就行了。
但是,问题来了:这种思路需要遍历链表两次,第一次统计出链表中结点的个数,第二次才能找到倒数第k个结点。
*/
Link* FindK2(Link *head,int k)
{
Link *p;
p=head;
int count=0;
while (count<6-k)
{
p=p->next;
count++;
}
return p;
}
/*
可行且高效的解法:为了能够只遍历一次就能找到倒数第k个节点,可以定义两个指针:
(1)第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;
(2)从第k步开始,第二个指针也开始从链表的头指针开始遍历;
(3)由于两个指针的距离保持在k-1,当第一个(走在前面的)指针到达链表的尾结点时,
第二个指针(走在后面的)指针正好是倒数第k个结点。
*/
Link* FindK1(Link *head,int k)
{
if(head == null || k == 0) return null;
Link *p1,*p2;
p1=head;
p2=NULL;
for(int i=0;i<k;i++)
{
if(p1->next !=NULL) p1=p1->next;
else return null;
}
p2=head;
while(p1)
{
p1=p1->next;
p2=p2->next;
}
return p2;
}
int main()
{
Link *head,*p1,*p2;
int a[6]={1,2,3,4,5,6};
head=createLink(a);
p1=FindK1(head,3);
p2=FindK2(head,3);
printf("%d",p1->data);
printf("%d",p2->data);
return 0;
}
今日面试题,拿来回忆回忆。