面試題:輸入一個鏈表,輸出該鏈表中倒數第k個結點。

直接上代碼,希望大家喜歡。`

//輸入一個鏈表,輸出該鏈表中倒數第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;
}

今日面試題,拿來回憶回憶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章