常规思路:(未知单链表长度情况下)遍历一遍单链表查询长度n,然后在遍历一遍查询第n-k个数即可。
优化思路:设置两个指针,让指针A先循环跑到第k个位置,然后两个指针同时跑,当A指针到达链表末尾时候,指针B所指即为倒数第k个数。这主要是在A和B之间固定了一个长度k,这样保持长度不变情况下即可得到答案。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
#define maxm 1000
typedef long long LL;
typedef int ElemType;
typedef struct node
{
int data;
struct node *next;
}node,*Linklist;
Linklist CreatList(Linklist &L,int n)//采用尾插法建立单链表
{//这里L传的是引用(会改变内容),需要注意
L=new node;//delete L
//L=(Linklist)malloc(sizeof(node));free L
//两种动态分配内存,以及释放内存方式
node *s,*r=L;//表尾指针
while(n--)
{
int x;
s=(Linklist)malloc(sizeof(node));
scanf("%d",&x);
s->data=x;
r->next=s;
r=s;
}
r->next=NULL;
return L;
}
int Search1(Linklist L,int k,int n)//常规代码
{
if(k<0||k>n) return 0;
int cnt=0;
Linklist p=L->next;//这里可以想一想为什么不是L>>看建表那儿
while(p)
{
p=p->next;
++cnt;
if(cnt==n-k) return p->data;
}
return 1;
}
int Search2(Linklist L,int k,int n)//优化思路代码
{
Linklist p1=L,p2=L;
int cnt=0;
if(k<0||k>n) return 0;
while(p1->next)
{
cnt++;
if(cnt<k) p1=p1->next;
else
{
p1=p1->next;
p2=p2->next;
}
}
return p2->data;
}
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
Linklist L=CreatList(L,n);
int ans1=Search1(L,k,n);
int ans2=Search2(L,k,n);
printf("%d\n",ans1);
printf("%d\n",ans2);
}
return 0;
}