直接上代碼,希望大家喜歡。`
//輸入一個鏈表,輸出該鏈表中倒數第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;
}
今日面試題,拿來回憶回憶。