使用以下作为链表的存储结构。带有头结点,其数值为-1。
typedef struct LNode
{
struct LNode* next;
int data;
}LNode, *LinkList;
考虑以下题目
1. 反向输出链表
使用递归。第一次三分时写完,五分时完成调试;第二次六分钟共用完成调试。
void printReverseLinkList_2(LinkList h)
{
if(h == NULL)
{
printf("\n");
return;
}
printReverseLinkList_2(h->next);
if(h->data != -1)
printf("%d, ", h->data);
}
2. 用O(1)的空间复杂度反转链表
一开始以为不断将最后一个元素头插,就可以实现反转,但并不是这样。如果是O(n),使用头插入将很简单,但是O(1)实现这点要求我们更新插入位置。第一次6分时写完,13分时调试完毕;第二次6分时写完,18分钟时调试完毕。
void reverseLinkList_2(LinkList h, int len)
{
if(len == 0 || len == 1) return;
LNode* pretail = h;
LNode* tail = pretail->next;
LNode* insertPos = h;
while(insertPos->next != NULL)
{
pretail = h;
tail = pretail->next;
while(tail->next != NULL)
{
pretail = pretail->next;
tail = tail->next;
}
pretail->next = NULL;
tail->next = insertPos->next;
insertPos->next = tail;
insertPos = insertPos->next;
}
}
3. 在链表中实现冒泡排序
这个题目可以很好地考察我们对链表的基本操作,查询,插入等。第一次和第二次完成同时间,10分时写完,11分时调试完毕。
void sortLinkList_2(LinkList h, int len)
{
LNode* pre = h;
LNode* cmp1 = pre->next;
LNode* cmp2 = pre->next->next;
int i = 0, j = 0;
for(i = len - 1; i >= 0; i--)
{
pre = h;
cmp1 = pre->next;
cmp2 = pre->next->next;
for(j = 0; j < i; j++)
{
if(cmp1->data > cmp2->data)
{
cmp1->next = cmp2->next;
cmp2->next = cmp1;
pre->next = cmp2;
}
pre = pre->next;
cmp1 = pre->next;
cmp2 = pre->next->next;
}
}
}
4. 设置一个递归算法,删除不带头结点的单链表L中所有值为x的结点
6分钟写完,14分钟调试完毕,感觉较慢
void deleteXRecursively(LinkList l, int x)
{
if(l->next == NULL) return;
else if(l->next->data == x)
{
l->next = l->next->next;
deleteXRecursively(l, x);
}
else
deleteXRecursively(l->next, x);
}
5. 给定两个链表,找出两个链表的公共结点
本题想到了暴力的方法,使用两个指针组合地遍历两个链表,复杂度为O(len1 * len2)。8分钟写完并调试完毕,感觉较慢。
在思考过程中我注意到了如果两个链表有公共结点,那么应该是“Y”的形状,但是没有想清楚怎么利用这个点。一开始我所想的是从两个链表的结尾开始遍历,但是如何从单链表结尾开始遍历就是一个难题。答案中想到了先求出两个链表长度之差s,然后长的链表领先s个单位进行比较,是一个巧妙的方法。
答案中的方法写出来8分钟。
LNode* findPublicLNode(LinkList m, LinkList n)
{
LNode* i;
LNode* j; //i for m, j for n
for(i = m; i != NULL; i = i->next)
for(j = n; j != NULL; j = j->next)
if(i == j)
return i;
return NULL;
}
int getLenLinklist(LinkList h)
{
int len = 0;
LNode* k = h->next;
while(k != NULL)
{
len++;
k = k->next;
}
return len;
}
LNode* findPublicLNode_2(LinkList m, LinkList n)
{
int lm = getLenLinklist(m);
int ln = getLenLinklist(n);
LNode* i = m;
LNode* j = n;
int d = lm - ln;
int k = 0;
if(d > 0)
for(k = 0; k < d; k++) i = i->next;
else
for(k = 0; k < d; k++) j = j->next;
while(i != NULL)
{
if(i == j) return i;
i = i->next;
j = j->next;
}
return NULL;
}