多个有序32位整数集合求交

  • 题目:多个有序32位整数集合求交 int32
  • 例如:A = {0, 1, 3, 4}, B = {1, 4, 5}, C = {0, 1, 4}, A&B&C的交集为{1, 4}
  • 要求:设计函数接口并实现算法, 计算和空间复杂度尽可能低
class Solution{
public:
/*
方法01:维护一个哈希表umap,遍历所有集合的所有元素arr[i][j];
    之后遍历哈希表umap,如果存在某元素的值umap[k]等于集合的个数arr.size(),即将其保存到结果集合中;
缺点:空间复杂度较高,需要维护一个哈希表umap,哈希表的大小为集合的不同整数的数目;
*/
    vector<int> arrayIntersection01(vector<vector<int>> &arr){
        vector<int> ret; 
        int len01 = arr.size();
        unordered_map<int,int> umap;
        for(int i = 0; i < len01; i++){
            int len02 = arr[i].size();
            for(int j = 0; j < len02; j++){
                umap[arr[i][j]]++;
            }
        }
        int len03 = umap.size();
        for(int k = 0; k < len03; k++){
            if(umap[k] == len01){   
                ret.push_back(k);
            }
        }
        return ret;
    }

/*
方法02:采用二路归并的思路;核心思想:二路归并+两集合相交;
    eg: step01: A=A交B、C=C交D、E=E交F、...
        step02: A=A交C、E=E交G、...
        ...
        step0n: A=A交X
        retuern: A
*/
    #include<algorithm>
    // 两集合相交方法01_使用算法count:
    vector<int> ArrIntersection01(vector<int> &vec1, vector<int> &vec2){
        vector<int> vec;
        int index = 0;
        for(int i = 0; i < vec1.size(); i++){
            if(count(vec2.begin(), vec2.end(), vec1[i])) vec[index++] = vec1[i];
        }
        vec1 = vec;
        return vec1;
    }
    // 两集合相交方法02_双指针的方法:
    vector<int> ArrIntersection02(vector<int> &vec1, vector<int> &vec2){
        vector<int> vec;
        int i = 0,j = 0,index = 0;
        while(i < vec1.size() && j < vec2.size()){
            if(vec1[i] < vec2[j]){
                i++;
            }else if(vec1[i] > vec2[j]){
                j++;
            }else{
                vec[index++] = vec1[i];
            }
        }
        vec1 = vec;
        return vec1;
    }
    // 两集合相交方法03_使用set的count特性:
    #include <set>
    vector<int> ArrIntersection03(vector<int> &vec1, vector<int> &vec2){
        vector<int> vec;
        set<int> st1;
        set<int> st2;
        for(int i : vec1) st1.insert(i);
        for(int i : vec2){
            if(st1.count(i)){
                vec.push_back(i);
            }
        }
        vec1 = vec;
        return vec1;
    }
    #include <math.h>
    
    vector<int> ArrIntersection01(vector<int> &vec1, vector<int> &vec2);
    vector<int> ArrIntersection02(vector<int> &vec1, vector<int> &vec2);
    vector<int> ArrIntersection03(vector<int> &vec1, vector<int> &vec2);
    // 两路归并:
    vector<int> arrayIntersection02(vector<vector<int>> &arr){
        vector<int> ret;
        int turn = 1;
        int len = arr.size(); //集合的数量
        len = ceil(len/2);
        if(len == 1){
            if(arr.size() == 1){
                ret = arr[0];
            }else{
                ret =  ArrIntersection01(arr[0], arr[1]);
                // ret =  ArrIntersection02(arr[0], arr[1]);
                // ret =  ArrIntersection03(arr[0], arr[1]);
            }
        }
        // 在归并的过程中,每次集合的数量为之前集合的1/2向上取整,当最终集合的大小为1时,停止操作
        while(len != 1){
            // 每轮归并需要求交集的次数
            for(int i = 0; i < len; i++){
                // 第一个求交集的下标为0=01 2=23 4=45 6=67 ... 
                // 第二次求交集的下标为0=02 4=46 8=8a ...
                // 第三次求交集的下标为0=04...
                // 下标的递增由1-2-4-8 对应变量 turn:1-2-4-8...

                // 需要判断访问的元素是否超过数组大小
                if((i+turn) > (arr.size() - 1)){
                    continue;
                }else{
                    arr[i] = ArrIntersection01(arr[i], arr[i+turn]); 
                    //arr[i] = ArrIntersection02(arr[i], arr[i+turn]); 
                    //arr[i] = ArrIntersection03(arr[i], arr[i+turn]); 
                }
                i += 2*turn;
            }
            // 每归并一次,剩余的集合数目
            len = ceil(len/2);
            turn = 2*turn;
        }
        // 最终结果保存到第一个集合
        ret = arr[0];
        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值