出现位置:第一轮基础类笔试或技术一面
难度系数:中
面试题目:
实现一个单链表的反转。例如:
10 9 8 7 6 5 4 3 2 1
反转后应该为:
1 2 3 4 5 6 7 8 9 10
要求10分钟内写出代码,注意代码风格及时间复杂度/空间复杂度。
考点分析:
(1)基本概念:链表基础,代码规范问题,代码健壮性问题。
(2)对时间复杂度的敏感。
解题思路:
“一问,二画,三答”
一问:问清题目,跟面试官交流,找出面试官看重什么,出题的目的是什么。
二画:不先写代码,先理清思路,在纸上画一画。
初步思路如下:
1、额外再申请一个链表,使用前插入的方法即可。(涉及到空间复杂度的问题)
2、先找最后一个,再找倒数第二个。(涉及到时间复杂度的问题)
所以,以上两条都不满足条件。这时就得和面试官交流是不是重点考察复杂度的问题。
有的面试官直接要求时间复杂度为O(n)。
则可以有下面的解题思路:
next = temp->next; //一个初始状态
temp->next = prew; //改变指针的指向,实现反转
temp = next; //后移一位
prev = temp; //后移一位
循环的条件是temp!=NULL
写出规范的代码的话,需要考虑特殊情况:
1、NULL的时候
2、1个节点的时候
代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct node //定义了一个链表的结构体
{
int iData;
struct node *next;
}LNode, *LinkList; //typedef 是用后面的两个名字替代结构体类型名
LinkList Link_insert(LinkList p,int num)
{
LinkList temp = NULL;
temp = (LinkList)malloc(sizeof(LNode)); //为节点temp动态分配内存
if (NULL==temp)
{
perror("malloc"); //错误输出函数
exit(EXIT_FAILURE);
}
temp->iData=num;
temp->next=p;
p=temp;
return p;
}
void Link_print(LinkList temp)
{
while (temp!=NULL)
{
printf("%d\t",temp->iData);
temp = temp->next;
}
printf("\n");
}
LinkList reverse_link(LinkList list)
{
if (list==NULL || list->next==NULL)
return list;
LinkList temp,prev,next; //定义3个临时变量
prev = list; //prev进行初始化
temp = list->next; //temp从第二个节点开始(初始化)
prev ->next = NULL; //第一个节点的next要为NULL
while (temp != NULL) //构成一个循环体
{
next = temp->next;
temp->next=prev; //反转
prev = temp; //后移
temp = next; //后移
}
return prev; //返回最后一个节点,prev指向最后一个节点,它变成了新的链表的头
}
int main()
{
LinkList head = NULL;
int temp = 0;
int i;
for (i=0;i<10;i++)
{
printf("输入一个数:");
scanf("%d",&temp);
head = Link_insert(head,temp);
Link_print(head);
}
printf("在反转后:\n");
head = reverse_link(head);
Link_print(head);
return 0;
}