【问题标题】:How to compare 2 sets of arrays for distinct matches如何比较两组不同匹配的数组
【发布时间】:2018-06-26 09:40:37
【问题描述】:

假设我有 4 个整数数组:(我将它们称为主数组)

我还有 x 个单独的整数数组:(称这些为数据数组)

我希望能够计算出我有多少个数据数组,其中至少一个条目也在 4 个主数组之一中,但一个主数组只能使用一次。

理想情况下,我在 C# 中寻求解决方案,但伪代码就足够了。

一些例子:

给定主数组:

[1],
[2, 3],
[4, 5, 6, 7],
[8]

使用数据数组:

[1],
[2],
[3, 9]

结果应该是 2。

  • 数据数组 1 与 Master 1 匹配。
  • 数据数组 2 与 Master 2 匹配。
  • 数据数组 3 与 Master 2 匹配(但 Master 2 已被使用)。

使用数据数组:

[1],
[2, 8]
[2],
[9]

结果应该是 3。

  • 数据数组 1 与 Master 1 匹配。
  • 数据数组 2 与 Master 2 和 4 匹配(应该只计算一次,但以后的条目将决定使用哪一个)。
  • 数据数组 3 与 Master 2 匹配(上面匹配了 2,但匹配了 4)。
  • 数据数组 4 不匹配

【问题讨论】:

    标签: c# arrays algorithm linq


    【解决方案1】:

    看起来很简单:

    var masters = new[]
    {
        new[] { 1 },
        new[] { 2, 3 },
        new[] { 4, 5, 6, 7 },
        new[] { 8 }
    };
    
    var data = new[] 
    {
        new[] { 1 },
        new[] { 3, 9 },
        new[] { 2 },
    };
    
    // Has masters[i] already been "consumed"?
    var used = new bool[masters.Length];
    
    // The found indexes in masters. -1 if not found/already used
    var res = new int[data.Length];
    
    for (int i = 0; i < data.Length; i++)
    {
        // The default condition is "not found"
        res[i] = -1;
    
        for (int j = 0; j < masters.Length; j++)
        {
            // If masters[j] already used/consumed, then skip it
            if (used[j])
            {
                continue;
            }
    
            // We are looking for an intersection between masters[j] and data[i]
            if (masters[j].Intersect(data[i]).Any())
            {
                used[j] = true;
                res[i] = j;
                break;
            }
        }
    }
    

    那么你就可以简单了

    int count = res.Count(x => x != -1);
    

    请注意,该算法的“时间”复杂度为 O(n^2)(如果我们考虑到 data[x].Length 的中等长度,则类似于 O(master.Length * data.Length)O(n^3)

    【讨论】:

    • 抱歉,int[][] data = new [] {new [] { 8, 2 }, new [] { 1 }, new [] { 2 },new [] { 9 }}; 是一个反例。预期:3,实际:2(除非贪婪算法必须被使用)
    • 你不会从 used.Count(c => c) 中得到计数吗?
    • @CeejeeB 因为我将-1 保存为“失败”
    • @DmitryBychenko 这是先到先得的服务。 data[0] 使用 master[1] 因为它是第一个未使用的 master。
    • 先到先得不回答问题。在@DmitryBychenko 的回答中,它必须返回 3
    【解决方案2】:

    对不起,我的回答太早了,我已经从头开始重写了。我们有一个众所周知的图问题,确切地说是最大二分匹配。在哪里

    • 第 1 部分顶点master 数组
    • 第 2 部分顶点data 数组
    • 边缘:如果数据数组与主数组共享至少一项(交集不为空)

    完成此操作后,您可以解决问题

    https://www.geeksforgeeks.org/maximum-bipartite-matching/

    https://www.cs.cmu.edu/~ckingsf/bioinfo-lectures/matching.pdf

    【讨论】:

    • 如果 dataArrays 只包含一个数组 [1,2] 这将在它应该返回 1 时返回 2
    • @CeejeeB:你说的很对,这是一个反例。为没有找到众所周知的图形问题而感到羞耻。
    【解决方案3】:

    也许这不是完美的解决方案,但它确实有效

            int[,] master = new int[4,4];
            master[0,0]=1;
            master[1,0]=2;
            master[1,1]=3;
            master[2,0]=4;
            master[2,1]=5;
            master[2,2]=6;
            master[2,3]=7;
            master[3,0]=8;
            int[,] data = new int[3,2];
            data[0,0]=1;
            data[1,0]=2;
            data[2,0]=3;
            data[2,1]=9;
    
            bool [] usedmaster= new bool[4];
            for (int i=0;i<4;i++) usedmaster[i]=false;    
    
            for (int di=0;di<3;di++)
            {
                for (int dj=0;dj<2;dj++)
                {
                    if (data[di,dj]>0)
                    {
                        int mi=0,mj=0,k=0;
                        foreach (int n in master)
                        {
                            if (data[di,dj]==n)
                            {
                                string ss="";
    
                                    if (usedmaster[k]==true) ss="{but master "+(k).ToString()+ " used}";
    
                                Console.WriteLine("Data array "+(di).ToString()+" matched with master "+(k).ToString()+ss);
                                usedmaster[k]=true;
                                k+=1;
    
                                break;
                            }
                            mj +=1;
                            if (master[mi,mj]==0) 
                            {
                                k +=1;
                                mi +=1;
                                mj=0;
                            }
                            if (mj>3) 
                            {
                                mj=0;
                                mi +=1;  
                                k +=1;
                            }
                        }
                    }
                }
            }       
    

    【讨论】:

      猜你喜欢
      • 2017-06-08
      • 1970-01-01
      • 2020-05-25
      • 2021-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多