P38.21
有n个整数存放到链表L中,返回倒数第k个元素。
(1)算法的基本设计思想
遍历一遍链表,得到链表元素总数,然后再次遍历得到倒数第k个元素。
(2)代码如下
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LinkList CreatListend(LinkList &L)
{
int x;
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
scanf("%d", &x);
while (x != 9999)
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL;
return L;
}
void main()
{
int count;
LinkList L;
CreatListend(L);
LNode *p = L->next;
LNode *q = L->next;
printf("输入要查找的倒数第几个数\n");
scanf("%d", &count);
int num = 0;
while (p != NULL)
{
num++;
p = p->next;
}
int _count = num - count + 1;
if (_count <= 0)
{
printf("输入错误");
}
else
{
while (_count != 1)
{
q = q->next;
_count--;
}
printf("倒数第%d个数为%d", count, q->data);
}
}
(3)复杂度
时间复杂度O(n)
空间复杂度O(n)
较好的算法
(1)算法的基本设计思想
应该有这样一个事实,若想知道倒数的元素,则必须知道元素总数。那么,至少遍历一遍链表是必不可少的。之后最白痴的做法我已经在上面给出了,就是再遍历一次。这样,当查找最后一个元素的时候,情况是最糟的,需要遍历整整两次。为减少操作时间,需要优化的是第一次遍历之后的操作。第一次遍历是不可能避免的。
我们设两个指针p和q,p随着链表节点一个一个往下走,q则不动,知道p和q差距为k。那么,当p到达尾节点,q就是倒数第k个节点了。
这种算法的时间耗费仅仅是遍历一次,与上面算法最优的情况下相同。
要学习这种思想,这个算法还是不难想到的。
(2)代码
扫描二维码关注公众号,回复:
2652179 查看本文章
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode *next;
}LNode,*LinkList;
LinkList CreatListend(LinkList &L)
{
int x;
L = (LinkList)malloc(sizeof(LNode));
LNode *s, *r = L;
scanf("%d", &x);
while (x != 9999)
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL;
return L;
}
void main()
{
int count;
LinkList L;
CreatListend(L);
LNode *p = L->next;
LNode *q = L->next;
printf("输入要查找的倒数第几个数\n");
scanf("%d", &count);
int num = 0;
while (p != NULL)
{
num++;
if (num <= count)
p = p->next;
else
{
p = p->next;
q = q->next;
}
}
printf("倒数第%d个数为%d", count, q->data);
}
(3)
时间复杂度O(n)
空间复杂度O(n)
人家能得满分,我只能得10分。