📜  两个链表的并集和交集的 C++ 程序(1)

📅  最后修改于: 2023-12-03 15:35:56.930000             🧑  作者: Mango

两个链表的并集和交集的 C++ 程序

两个链表的并集和交集是指给定两个链表,找到它们的公共节点和所有节点。这个问题可以通过使用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链表的交集和并集。