假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可共享相同的后缀存储空间,例如,“loading”,“being”的存储映像如下图所示。
设str1和str2分别指向两个单词所在单链表的头结点,链表结点结构为
data next
请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后缀的起始位置(如图中字符i所在结点的位置p)
算法思想:
1.遍历两个单链表,分别计算出它们的长度。
2.如果两个链表的长度不相同,则将较长的那个链表的头指针往后移,使得两个链表剩余的长度相同。
3.同时遍历两个链表,比较节点是否相同,直至找到第一个相同的节点或遍历到链表的结尾。
4.输出或返回第一个相同节点的位置。
代码:(完整理解此题)
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
char data;
struct ListNode* next;
};
struct ListNode* findCommonSuffix(struct ListNode* str1, struct ListNode* str2) {
int len1 = getListLength(str1);
int len2 = getListLength(str2);
// 将较长链表的头指针向后移动,使得两个链表剩余的长度相等
if (len1 > len2) {
str1 = moveHead(str1, len1 - len2);
} else if (len2 > len1) {
str2 = moveHead(str2, len2 - len1);
}
// 同时遍历两个链表,比较节点是否相同
while (str1 != NULL && str2 != NULL) {
if (str1 == str2) {
return str1; // 找到第一个相同的节点
}
str1 = str1->next;
str2 = str2->next;
}
return NULL; // 没有找到共同后缀
}
// 获取链表的长度
int getListLength(struct ListNode* head) {
int length = 0;
while (head != NULL) {
length++;
head = head->next;
}
return length;
}
// 将链表的头指针向后移动指定步数
struct ListNode* moveHead(struct ListNode* head, int steps) {
for (int i = 0; i < steps; i++) {
head = head->next;
}
return head;
}
int main() {
// 构建示例链表
struct ListNode* node1 = (struct ListNode*)malloc(sizeof(struct ListNode));
node1->data = 'l';
node1->next = NULL;
struct ListNode* node2 = (struct ListNode*)malloc(sizeof(struct ListNode));
node2->data = 'o';
node2->next = NULL;
struct ListNode* node3 = (struct ListNode*)malloc(sizeof(struct ListNode));
node3->data = 'a';
node3->next = NULL;
struct ListNode* node4 = (struct ListNode*)malloc(sizeof(struct ListNode));
node4->data = 'd';
node4->next = NULL;
struct ListNode* node5 = (struct ListNode*)malloc(sizeof(struct ListNode));
node5->data = 'i';
node5->next = NULL;
struct ListNode* node6 = (struct ListNode*)malloc(sizeof(struct ListNode));
node6->data = 'n';
node6->next = NULL;
struct ListNode* node7 = (struct ListNode*)malloc(sizeof(struct ListNode));
node7->data = 'g';
node7->next = NULL;
// 构建链表结构
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = node5;
node5->next = node6;
node6->next = node7;
struct ListNode* str1 = node1;
// 构建示例链表
struct ListNode* node8 = (struct ListNode*)malloc(sizeof(struct ListNode));
node8->data = 'b';
node8->next = NULL;
struct ListNode* node9 = (struct ListNode*)malloc(sizeof(struct ListNode));
node9->data = 'e';
node9->next = NULL;
struct ListNode* node10 = (struct ListNode*)malloc(sizeof(struct ListNode));
node10->data = 'i';
node10->next = NULL;
struct ListNode* node11 = (struct ListNode*)malloc(sizeof(struct ListNode));
node11->data = 'n';
node11->next = NULL;
struct ListNode* node12 = (struct ListNode*)malloc(sizeof(struct ListNode));
node12->data = 'g';
node12->next = NULL;
// 构建链表结构
node8->next = node9;
node9->next = node10;
node10->next = node11;
node11->next = node12;
struct ListNode* str2 = node8;
// 调用函数查找共同后缀
struct ListNode* commonSuffix = findCommonSuffix(str1, str2);
if (commonSuffix != NULL) {
printf("共同后缀的起始位置为:%c\n", commonSuffix->data);
} else {
printf("未找到共同后缀\n");
}
// 释放内存
free(node1);
free(node2);
free(node3);
free(node4);
free(node5);
free(node6);
free(node7);
free(node8);
free(node9);
free(node10);
free(node11);
free(node12);
return 0;
}
{
}