📅  最后修改于: 2023-12-03 15:35:56.930000             🧑  作者: Mango
两个链表的并集和交集是指给定两个链表,找到它们的公共节点和所有节点。这个问题可以通过使用C++编程语言来解决。
要实现这个问题的解决,需要考虑以下几个步骤:
1.创建两个链表
2.找到两个链表的交集,即它们共同指向的节点
3.找到两个链表的并集,即两个链表中不相交部分的所有节点和交集的所有节点
实现这个问题的解决,需要使用链表的数据结构和C++的程序语言。
在C++程序中创建链表,可以使用节点(node)和指针(pointer)的结构。
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
Solution(){};//构造函数
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
int lengthA = length(headA);//获取链表A的长度
int lengthB = length(headB);//获取链表B的长度
if(lengthA > lengthB) {//交换交换链表顺序保证链表A更短
swap(headA, headB);
swap(lengthA, lengthB);
}
int d = lengthB - lengthA;//计算链表B与链表A长的长度
for(int i = 0; i < d; ++i) {
headB = headB->next;
}
for(int i = 0; i < lengthA; ++i) {
if(headA == headB) return headA;
headA = headA->next;
headB = headB->next;
}
return NULL;
}
int length(ListNode* node){//获取链表的长度
int length = 0;
while(node){
length++;
node = node->next;
}
return length;
}
};
由于我们要实现两个链表的交集和并集,我们需要处理它们的指针,以便我们能够正确地找到它们的公共节点和所有节点。
要找到两个链表的交集,我们需要实现一个函数:getIntersectionNode(headA, headB)。这个函数的基本思路如下:
1.获取链表A和B的长度
2.如果链表A更长,请将它们交换,以便我们可以更快地找到交点
3.将链表B指针向前移动d个节点,这是链表B与链表A的差异之处
4.如果链表A和B当前指向的节点相同,则返回该节点
5.否则,将链表A和B的指针都向前移动一个节点,重复步骤4和5,直到找到交点或到达链表的末尾
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
int lengthA = length(headA);//获取链表A的长度
int lengthB = length(headB);//获取链表B的长度
if(lengthA > lengthB) {//如果链表A更长,就交换它们
swap(headA, headB);
swap(lengthA, lengthB);
}
int d = lengthB - lengthA;//计算两个链表之间的长度差
//将链表B的指针移到与链表A的指针相同的位置
for(int i = 0; i < d; ++i) {
headB = headB->next;
}
//查找交点
for(int i = 0; i < lengthA; ++i) {
if(headA == headB) return headA;//找到交点
headA = headA->next;
headB = headB->next;
}
return NULL;//没有交点
}
要找到两个链表的并集,我们可以用以下方法来实现:
1.将链表A的所有元素插入到哈希表中,并设置value为1
2.对于链表B中的每个元素,检查它是否在哈希表中。
3.如果它在哈希表中,就将value设置为2。
4.否则,将该元素插入哈希表中,设置value为1
5.遍历哈希表,所有value为1的节点都是A和B链表的并集,所有value为2的节点都是交集。
class Solution {
public:
Solution(){};
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
int lengthA = length(headA);
int lengthB = length(headB);
if(lengthA > lengthB) {
swap(headA, headB);
swap(lengthA, lengthB);
}
int d = lengthB - lengthA;
//将链表B的指针移到与链表A的指针相同的位置
for(int i = 0; i < d; ++i) {
headB = headB->next;
}
//查找交点
for(int i = 0; i < lengthA; ++i) {
if(headA == headB) return headA;
headA = headA->next;
headB = headB->next;
}
return NULL;
}
int length(ListNode* node){
int length = 0;
while(node){
length++;
node = node->next;
}
return length;
}
ListNode* getUnion(ListNode* headA, ListNode* headB){
if(!headA && !headB) return NULL;//如果两个链表都是空的,则返回空指针
unordered_map<int, int> map;//哈希表
ListNode* p = headA;
ListNode* q = headB;
ListNode* headU = new ListNode(0);
ListNode* tail = headU;//尾指针
while(p){//遍历A链表
if(map.find(p->val) == map.end()){//如果p节点的值在哈希表中没有出现过
map[p->val] = 1;
ListNode* temp = new ListNode(p->val);
tail->next = temp;
tail = temp;
}else{//如果p节点的值在哈希表中出现过,并且当前节点是第一个在A链表中出现的
if(map[p->val] == 1){
map[p->val] = 2;//将哈希表中的value值改为2,表示已经在B链表中出现过
}
}
p = p->next;
}
while(q){//遍历B链表
if(map.find(q->val) == map.end()){//如果q节点的值在哈希表中没有出现过
map[q->val] = 1;
ListNode* temp = new ListNode(q->val);
tail->next = temp;
tail = temp;
}else{//如果q节点的值在哈希表中出现过,并且当前节点是第一个在B链表中出现的
if(map[q->val] == 1){
map[q->val] = 2;//将哈希表中的value值改为2,表示已经在A链表中出现过
}
}
q = q->next;
}
return headU->next;
}
ListNode* getIntersection(ListNode* headA, ListNode* headB){
if(!headA || !headB) return NULL;//如果两个链表有一个是空的,则返回空指针
unordered_map<int, int> map;//哈希表
ListNode* p = headA;
ListNode* q = headB;
ListNode* headI = new ListNode(0);
ListNode* tail = headI;//尾指针
while(p){//遍历A链表
if(map.find(p->val) == map.end()){//如果p节点的值在哈希表中没有出现过
map[p->val] = 1;
}
p = p->next;
}
while(q){//遍历B链表
if(map.find(q->val) != map.end()){//如果q节点的值在哈希表中存在
if(map[q->val] == 1){//如果值为1,表示q节点是第一个出现在A链表中的节点
map[q->val] = 2;//将哈希表中的value值改为2,表示q节点也在B链表中出现过
ListNode* temp = new ListNode(q->val);
tail->next = temp;
tail = temp;
}
}
q = q->next;
}
return headI->next;
}
void print(ListNode* node){//打印链表
while(node){
cout << node->val << " ";
node = node->next;
}
cout << endl;
}
};
int main(){
Solution solution;
//创建两个链表 1->2->3->4->5 和 2->3->4
ListNode* na1 = new ListNode(1);
ListNode* na2 = new ListNode(2);
ListNode* na3 = new ListNode(3);
ListNode* na4 = new ListNode(4);
ListNode* na5 = new ListNode(5);
na1->next = na2;
na2->next = na3;
na3->next = na4;
na4->next = na5;
ListNode* nb1 = new ListNode(2);
ListNode* nb2 = new ListNode(3);
ListNode* nb3 = new ListNode(4);
nb1->next = nb2;
nb2->next = nb3;
//打印两个链表
solution.print(na1);
solution.print(nb1);
//找到两个链表的交集
ListNode* intersection = solution.getIntersectionNode(na1, nb1);
if(intersection) cout << intersection->val << endl;
//找到两个链表的并集
ListNode* union_list = solution.getUnion(na1, nb1);
solution.print(union_list);
//找到两个链表的交集
ListNode* intersection_list = solution.getIntersection(na1, nb1);
solution.print(intersection_list);
return 0;
}
通过使用C++语言和链表的数据结构,可以很容易地解决找到两个链表的交集和并集的问题。我们只需要实现getIntersectionNode(headA, headB),getUnion(headA, headB)和getIntersection(headA, headB)函数来处理它们两个的指针。设计哈希表来存储链表元素的值,可以快速地找到它们是否相等。完成这些步骤后,我们就可以轻松地找到A和B链表的交集和并集。