【问题标题】:Union of two sorted arrays in c++c ++中两个排序数组的并集
【发布时间】:2021-11-29 13:22:02
【问题描述】:

我收到 SEGMENTATION FAULT,因为错误有人可以帮我找出我的错误, 我意识到这不是最优化的代码,任何建议都会有所帮助,谢谢

问题:

给定两个数组a[]b[],大小分别为nm。任务是找到这两个数组之间的联合。

两个数组的并集可以定义为包含两个数组中不同元素的集合。如果有重复,则只应在联合中打印一次出现的元素。

示例 1:

输入:

5 3
1 2 3 4 5
1 2 3

输出:

5

解释:

1、2、3、4 和 5 是 联合集中的元素 两个数组。所以计数是 5。

示例 2:

输入:

6 2 
85 25 1 32 54 6
85 2 

输出:

7

说明: 85、25、1、32、54、6 和 2是进来的元素 两个数组的联合集。所以计数是7。 你的任务: 完整的 doUnion 函数,以 a、n、b、m 为参数并返回两个数组的联合元素的计数。打印由驱动代码完成。

约束:

1 ≤ n, m ≤ 105
0 ≤ a[i], b[i] < 105

预期时间复杂度:O((n+m)log(n+m)) 预期辅助空间:O(n+m)

我的回答:

//Function to return the count of number of elements in union of two arrays.
    int doUnion(int a[], int n, int b[], int m)  {
        //code here
        int mac;
            if(a[n-1]>=a[n-2] && a[n-2]>=a[n-3]){
                mac=a[n-1];
            }else{
                mac=a[0];
            }
            int mab;
            if(b[m-1]>=b[m-2] && b[m-2]>=b[m-3]){
                mab=b[m-1];
            }else{
                mab=b[0];
            }
            // cout<<mac<<" "<<mab<<endl;
        
        int ma = max(mac,mab);
        int ptr[ma+1]={0};
        
        for(int i = 0;i<n;i++)
        {
            ptr[a[i]]++;
        }
        for(int i=0;i<m;i++)
        {
            ptr[b[i]]++;
        }
        int u=0;
        
        for(int i=0;i<=ma;i++){
            if(ptr[i]>0)
            {
                // cout<<i<<endl;
                u++;
            }
        }
        return u;
        
    }

【问题讨论】:

  • C++ 已经提供了这个特性,q.v. set_intersection.
  • 所以让我们看看:{100}, 1, {101}, 1 segfaults on a[-2] access(为什么还要尝试呢?),如果没有,它会尝试分配大小为 102 的 ptr (这也不是预期的辅助尺寸)。 (插入关于可变长度数组不是有效的 C++ 的强制性说明)你确定你不想考虑一下你在做什么吗?
  • sorted这个词在标题中徘徊,但考虑到问题主体,感觉有点孤独。输入是否实际排序?这确实对解决方案产生了影响。我们可以有一个包含一些数据的minimal reproducible example 吗?
  • 实际上,如果它是预先排序的,您可以在 O(n+m) 时间内使用 O(1) 辅助空间来完成此操作。所以我认为标题是错误的。 “预期时间复杂度:O((n+m)log(n+m)) 预期辅助空间:O(n+m)”建议“将所有内容复制到一堆,排序,计数唯一数字”作为预期解决方案。
  • 使用向量会容易得多。

标签: c++ algorithm data-structures


【解决方案1】:

这里是 C++ 解决方案,保留 C-Style 数组函数原型。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>

int doUnion(int a[], int n, int b[], int m) {
    std::vector<int> result{};
    std::set_intersection(a, a + n, b, b + m, std::back_inserter(result));
    return result.size();
}


int main() {
    int a[] = { 1,2,3,4,5,6,7,8,9 };    
    int b[] = {     3,    6,      10,11,12    };
    std::cout << doUnion(a, 9, b, 5);
}

如果你想拥有真正低级的东西,那么请看下面那个丑陋的:

int doUnion(int a[], int n, int b[], int m) {

    int* x = a;
    int* y = b;
    int counter = 0;

    while (x != (a + n) && y != (b + m)) {
        if (*x < *y) ++x;
        else {
            if (!(*y < *x)){ ++x; ++counter;}
            ++y;
        }
    }
    return counter;
}

【讨论】:

  • 你确定 OP 的输入实际上是排序的吗?如果没有,您的解决方案将不起作用。还有#2的“预期辅助空间:O(n + m)”呢?
  • 不,我不确定。当然输入需要排序。如果没有排序,那么让我们使用 std::sort 对其进行排序。关于辅助空间。它应该是 m+n。我做错了什么?也许是一些幼稚的错字?请纠正我,然后我将编辑问题。
  • 我很确定尽管标题中出现了单词,但它们实际上并没有排序(参见 cmets)。 212 (int result[212];) 不是 O(n+m),如果我们放宽对 m 和 n 的限制,你会使用什么大小?而且您只需要计数,因此您实际上可以在 O(1) 存储中完成等效操作。 (那么为什么需要 O(n+m)?因为输入实际上没有排序......)
  • 不知何故,我相信问题标题中的“排序”一词。 . .但我会删除答案。反正没人会用它
【解决方案2】:

这是我的版本,使用向量:

已编辑:更改了代码以返回唯一值的数量。

int doUnion(int a[], int n, int b[], int m)
{
     std::vector<int> the_union;
     for (int i = 0; i < n; ++i)
     {
         the_union.push_back(a[i]);
     }
     for (int i = 0; i < m; ++i)
     {
         the_union.push_back(b[i]);
     }
     std::sort(the_union.begin(), the_union.end());
     std::vector::iterator union_end_iter =  
         std::unique(the_union.begin(), the_union.end());

     // The `std::unique` does not remove the duplicate elements.
     the_union.erase(union_end_iter, the_union.end());
     // Return the number of unique elements:
     return the_union.size();
}

算法是:

  1. 将所有两个数组合并为一个向量。
  2. 对矢量进行排序(这使下一步更容易)。
  3. 删除所有重复值,以便向量中只有唯一值。
  4. 返回向量的大小,即唯一值的个数。

【讨论】:

  • 使用动态分配的数组可以提高效率。但问题是,节省了多少时间,是不是可以忽略不计。
  • @dratenik:谢谢。进行了适当的修改。
猜你喜欢
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 2018-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多