首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从3个重叠列表中获取3个唯一项?

如何从3个重叠列表中获取3个唯一项?
EN

Stack Overflow用户
提问于 2016-04-29 18:51:17
回答 3查看 122关注 0票数 0

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

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

例如:

总榜单:苹果、梨、香蕉

清单一:苹果、梨

清单2:香蕉

清单三:香蕉、苹果

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

总榜单:苹果、梨、香蕉

清单一:苹果、梨

清单二:苹果、梨

清单三:苹果、梨

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

这是一个游戏,所以我需要它是有效的!提前谢谢。

EN

回答 3

Stack Overflow用户

发布于 2016-04-29 19:08:39

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

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

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

票数 2
EN

Stack Overflow用户

发布于 2016-04-29 19:16:39

假设你有list αβɣ

ABC = α ∩ β ∩ ɣ

AB = α ∩ β \ ABC

AC = α ∩ ɣ \ ABC

BC = β ∩ ɣ \ ABC

A = α \ (β ∪ ɣ)

B = β \ (α ∪ ɣ)

C = ɣ \ (α ∪ β)

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

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

示例实现:

代码语言:javascript
复制
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;
}
票数 0
EN

Stack Overflow用户

发布于 2016-04-29 19:52:26

我认为你可以这样做:

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

例如,你的第一个例子:苹果,梨,香蕉

代码语言:javascript
复制
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个列表,那么你的check数组将包含n个元素。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36936413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档