【问题标题】:How do I get 3 unique items from 3 overlapping lists?如何从 3 个重叠列表中获取 3 个唯一项目?
【发布时间】:2016-08-24 12:01:54
【问题描述】:

这与仅在每个列表中查找唯一或不同的项目不同。

我有 3 个引用对象列表,每个列表可以包含相同的项目(但每个项目只能包含一次)。我想对以下问题给出是/否的答案:在每个列表中取一项,是否有可能没有重复项?

例如:

总表:苹果、梨、香蕉

清单 1:苹果、梨

清单 2:香蕉

清单 3:香蕉、苹果

结果:TRUE(可以从每个列表中选择一项并有 3 个唯一项)

总表:苹果、梨、香蕉

清单 1:苹果、梨

清单 2:苹果、梨

清单 3:苹果、梨

结果:FALSE(不能从每个列表中选择一项并且有 3 个唯一项)

这是为了游戏,所以我需要它高效!提前致谢。

【问题讨论】:

  • 解决此问题的一种方法是创建一棵树,每个级别都有来自一个列表的所有可能性。之后,使用任何树搜索算法都可以。
  • 谢谢...我用谷歌搜索了树木,但我不知道如何为我的案例实施!
  • 我认为你应该改写这个我可以从每个列表中选择一个项目并确保每个选择的项目都与其他选择的项目不同吗?类似于,说 在每个列表中取一项,是否有可能没有重复?
  • 感谢 hoang,已按照您的建议进行了编辑。

标签: c# list unique


【解决方案1】:

这是 NP-Hard 问题 Constraint satisfaction problem see here。 换句话说,你有组 {a,b,c,d} 并且你想找到(a or b) and (b or c) and...

但是,如果您事先知道所有可能的选项,您可以创建一个列表\值的字典(较小列表的散列值)并在运行时检查列表。

如果不是,您可以使用其中一种 CSP 求解算法。

【讨论】:

  • 我确实提前知道了 3 个列表的内容(我创建了所有 3 个列表,然后进行比较)。但是,“只需创建一个列表/字典并检查列表”并不是特别有用!
  • 如果这不是“特别有用”,那么到目前为止您到底尝试了什么?现在,您似乎正在寻找某人为您做作业。
  • 没有帮助是什么意思?你要代码吗?创建字典很简单,哈希也很简单......
  • 是的,我可以创建一个字典,我只需要推动这个想法的实际应用——而不是整个代码。这里的答案是检查每一个组合吗?如果是这样,那我觉得效率不是很高...
  • 算法如下:计算并保存(仅第一次)所有选项 h = hash({a,b},{b,c},{c}) 保存在字典中 Dict
【解决方案2】:

我认为你可以这样做:

您获取整个列表中的第一项,然后检查 3 个“目标”列表中的每一个以查看它出现在哪个列表中。将这些检查结果存储在一个 3 元素数组中(每个目标列表一个元素)-说 0 表示不发生,而 1 表示确实发生。 然后对整个列表中的第二个项目再次执行此操作,依此类推。 因此,您最终将得到一个包含 3 个元素数组的“检查列表”(列表长度等于整个数组中的项目数。 然后将检查列表中每个数组的第一个元素、第二个元素和第三个元素相加。只要每个总和大于 0,您的测试就会通过。

例如对于你的第一个例子 总表:苹果、梨、香蕉

Check results:
Item 1 (apple)  : 1 0 1 (apple occurs in list 1 and 3)
Item 2 (pear)   : 1 0 0 
Item 3 (banana) : 0 1 1
Total             2 1 2 (result is a pass)

您的第二个示例将失败,因为您将有两个 1 1 0 的检查数组,当您将每个这些数组中的第三个元素相加时,您将得到 0。

我认为这可以轻松扩展到任意数量的目标列表 - 如果您有 n 个列表,则每个检查数组将包含 n 个元素。

【讨论】:

    【解决方案3】:

    假设您有列表αβɣ

    ABC = α ∩ β ∩ ɣ
    AB = α ∩ β \ ABC
    AC = α ∩ ɣ \ ABC
    BC = β ∩ ɣ \ ABC
    A = α \ (β ∪ ɣ)
    B = β \ (α ∪ ɣ)
    C = ɣ \ (α ∪ β)

    让 |X|是集合 X 的基数。

    当且仅当|A| + |B| + |C| + |AB| + |AC| + |BC| + |ABC| >= 3返回true

    示例实现:

    void Main()
    {
        var alpha = new List<string> { "apple", "pear", };
        var beta = new List<string> { "banana", };
        var gamma = new List<string> { "banana", "apple", };
    
        Console.WriteLine(Compute(alpha, beta, gamma));
        Console.WriteLine(ComputeWithSets(alpha, beta, gamma));
    
        alpha = new List<string> { "apple", "pear", };
        beta = new List<string> { "apple", "pear", };
        gamma = new List<string> { "apple", "pear", };
    
        Console.WriteLine(Compute(alpha, beta, gamma));
        Console.WriteLine(ComputeWithSets(alpha, beta, gamma));
    
        alpha = new List<string> { "apple", "pear", "banana", };
        beta = new List<string> { "apple", "pear", "banana", };
        gamma = new List<string> { "apple", "pear", "banana", };
    
        Console.WriteLine(Compute(alpha, beta, gamma));
        Console.WriteLine(ComputeWithSets(alpha, beta, gamma));
    }
    
    bool Compute(List<string> alpha, List<string> beta, List<string> gamma)
    {
        if (alpha.Count == 0) return false;
        if (beta.Count == 0) return false;
        if (gamma.Count == 0) return false;
    
        foreach (var a in alpha)
            foreach (var b in beta)
                if (a != b)
                    foreach (var c in gamma)
                        if (c != a && c != b)
                        {
                            Console.Write(string.Format("{0},{1},{2} =>", a, b, c));
                            return true;    
                        }
        return false;
    }
    
    bool ComputeWithSets(List<string> alpha, List<string> beta, List<string> gamma)
    {
        var abc = alpha.Intersect(beta.Intersect(gamma));
        var abcCardinality = abc.Count();
    
        var count = abcCardinality;
        if (count >= 3) return true;
    
        var ab = alpha.Intersect(beta).Except(abc);
        count += ab.Count();
        if (count >= 3) return true;
    
        var bc = beta.Intersect(gamma).Except(abc);
        count += bc.Count();
        if (count >= 3) return true;
    
        var ac = alpha.Intersect(gamma).Except(abc);
        count += ac.Count();
        if (count >= 3) return true;
    
        var a = alpha.Except(ab).Except(ac).Except(abc);
        count += a.Count();
        if (count >= 3) return true;
    
        var b = beta.Except(ab).Except(bc).Except(abc);
        count += b.Count();
        if (count >= 3) return true;
    
        var c = gamma.Except(ac).Except(bc).Except(abc);
        count += c.Count();
        if (count >= 3) return true;
    
        return false;
    }
    

    【讨论】:

    • 在我的情况下不确定这是否正确:例如,所有三个列表可能相同并包含三个项目 - 这意味着您的插图中的 A、B 和 C 将不存在,但对于我的目的答案应该是正确的。
    • 更新了我的答案。如果所有三个列表都相同并且包含三个项目,那么您将拥有 |ABC| = 3 因此为真。
    猜你喜欢
    • 2017-07-15
    • 1970-01-01
    • 2010-11-26
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多