目录
题目
有两个单链表,要求返回最大公共后缀中第一个数据元素在第一个链表中等指针,如果不存在公共后缀,则返回NULL。比如La=(35,34,3,6,7),Lb=(3,6,7),则最大公共后缀为(3,6,7)。
一、解题思路
由于La和Lb的长度未知,同时注意到公共后缀其后面的数据元素一定相同,可以首先比较两链表的长度,将长的“剪”成和短的一样长度,再逐个比较数据元素,寻找公共后缀。比如题目中,La长为5,Lb长为3,因此两表的最大公共后缀长度必然小于等于3。
那么要怎么“剪”呢?很简单,只要把长的链表往后索引就行。
二、核心代码
1.链表定义
代码如下(示例):
typedef struct LNode
{
int data;
LNode* next = NULL;
}LNode, * LinkList; //Linklist相当于LNode*
获取两表长度 :
LinkList Lb_head = Lb; //记录头结点位置
LinkList La_head = La;
LinkList Max_head = NULL; //记录最大公共前缀的首位置
int length_a = 0;
int length_b = 0;
while (La->next!=NULL) //分别统计a和b的表长
{
length_a++;
La = La->next;
}
while (Lb->next != NULL) //分别统计a和b的表长
{
length_b++;
Lb = Lb->next;
}
2.将链表“剪”短
代码如下(示例):
int length = length_a - length_b;
if (length > 0) //a表长于b
{
while (length--)
La = La->next; //a向后移
}
if (length < 0) //a表短于b
{
length = -length;
while (length--)
Lb = Lb->next; //b向后移
}
3.寻找公共后缀
//经过上面比较和“裁剪”过后,La和Lb一样长
int _switch_ = 0; //设置开关,决定要不要将La->next赋给Max_head
while (La->next!=NULL && Lb->next!=NULL)
{
if (La->next->data == Lb->next->data && !_switch_)
{
Max_head = La->next;
_switch_ = 1; //开关置1
}
if (La->next->data != Lb->next->data)
{
_switch_ = 0; //手动置0
}
La = La->next; //La和Lb向后索引
Lb = Lb->next;
4.完整源码
#include<iostream>
using namespace std;
typedef struct LNode
{
int data;
LNode* next = NULL;
}LNode, * LinkList; //Linklist相当于LNode*
LinkList MaxList(LinkList La,LinkList Lb)
{
LinkList Lb_head = Lb; //记录头结点位置
LinkList La_head = La;
LinkList Max_head = NULL; //记录最大公共前缀的首位置
int length_a = 0;
int length_b = 0;
while (La->next!=NULL) //分别统计a和b的表长
{
length_a++;
La = La->next;
}
while (Lb->next != NULL) //分别统计a和b的表长
{
length_b++;
Lb = Lb->next;
}
La = La_head; //将La,Lb指回头结点
Lb = Lb_head;
int length = length_a - length_b;
if (length > 0) //a表长于b
{
while (length--)
La = La->next; //a向后移
}
if (length < 0) //a表短于b
{
length = -length;
while (length--)
Lb = Lb->next; //b向后移
}
//a和b一样长
int _switch_ = 0; //设置开关,决定要不要将La->next赋给Max_head
while (La->next!=NULL && Lb->next!=NULL)
{
if (La->next->data == Lb->next->data && !_switch_)
{
Max_head = La->next;
_switch_ = 1; //开关置1
}
if (La->next->data != Lb->next->data)
{
_switch_ = 0; //手动置0
}
La = La->next;
Lb = Lb->next;
}
return Max_head;
}
void Init(LinkList L) //初始化函数 初始化成:1 3 5 7 9
{
for (int i = 1; i < 10; i = i + 2)
{
LinkList p = new LNode;
L->next = p;
p->data = i;
L = L->next;
}
}
void main()
{
//利用函数初始化
LinkList La = new LNode;
Init(La);
LinkList La_0;
La_0 = La->next; //创建La_0的目的是用La_0来进行手动赋值,手动赋值过程中La_0=La_0->next会将结点位置往后推,
//此时La的作用是存储头结点位置,向后推之后依然可以用La找到a链表
//手动赋值La为 5 6 7 8 9
for (int i = 5; i < 10; i++)
{
La_0->data = i;
La_0 = La_0->next;
}
LinkList Lb = new LNode;
Init(Lb); //Lb为1 3 5 7 9
LinkList max_head;
max_head = MaxList(La, Lb);
//------------------------验证部分--------------------------//
if (max_head != NULL)
cout << max_head->data << endl; //用max_head->data验证max_head是否正确
else
cout << "max_head为空" << endl;
system("pause");
delete La;
delete Lb;
}
总结
解题思路明确了就好处理了,其余都是基础代码,欢迎评论区讨论指正