【问题标题】:How to search for the largest subset where every pair meets criteria?如何搜索每对符合条件的最大子集?
【发布时间】:2017-02-21 18:09:29
【问题描述】:

我希望这不是一个统计问题...

假设我有一个接口:

public interface PairValidatable<T>
{
    public boolean isValidWith(T);
}

现在,如果我有一个大数组 PairValidatables,我如何找到该数组的最大子集,其中每一对都通过了 isValidWith 测试?

澄清一下,如果一个子集中有三个条目,那么元素 0 和 1 应该通过 isValidWith,元素 1 和 2 应该通过 isValidWith,元素 0 和 2 应该通过 isValidWith。

例子,

public class Point implements PairValidatable<Point>
{
    int x;
    int y;

    public Point(int xIn, int yIn)
    {
        x = xIn;
        y = yIn;
    }

    public boolean isValidWith(Point other)
    {
        //whichever has the greater x must have the lesser (or equal) y
        return x > other.x != y > other.y;
    }
}

The intuitive idea是保留一个Points的向量,添加数组元素0,然后将剩余的每个数组元素与向量进行比较,如果它通过验证与向量中的每个元素,则将其添加到向量中......但问题是元素 0 可能非常严格。例如,

Point[] arr = new Point[5];
arr[0] = new Point(1000, 1000);
arr[1] = new Point(10, 10);
arr[2] = new Point(15, 7);
arr[3] = new Point(3, 6);
arr[4] = new Point(18, 6);

如上迭代将给我们一个仅包含元素 0 的子集,但元素 1、2 和 4 的子集是一个更大的子集,其中每一对都通过了验证。然后,该算法应返回存储在元素 1、2 和 4 中的点。虽然元素 3 和 4 彼此有效且元素 1 和 4 彼此有效,但元素 2 和 3 无效,元素 1 和 3 也无效。包含 1、2 和 4 的子集是比 3 和 4 更大的子集。

我猜想一些树或图算法最适合解决这个问题,但我不确定如何设置它。

解决方案不必是特定于 Java 的,最好可以用任何语言实现,而不是依赖于 Java 内置程序。出于熟悉的原因,我只是在上面使用了类似 Java 的伪代码。

【问题讨论】:

  • @Stephan 不完全是。子集中的每一对都应该从 isValidWith 返回 true。例如,a 可能对 b 有效,b 可能对 c 有效,但 c 可能对 a 无效。这意味着必须省略 a 或 c。我不确定我的示例方法是否会以这种方式运行,但解决方案应该包含这样的方法。
  • 您能否扩展您的问题以在示例中包含 3 个以上的条目,以及您期望的输出是什么?
  • 绘制出来,看起来您正在寻找边缘具有非负斜率的最大元素子集。这听起来准确吗?
  • @Stephan 这是一个很好的观察,虽然我认为你的意思是说非斜率。这样可以更轻松地解决该案例。

标签: algorithm search subset


【解决方案1】:

大概isValidWith 是可交换的——也就是说,如果x.isValidWith(y) 那么y.isValidWith(x)。如果您知道的仅此而已,则您有一个 maximum clique problem 的实例,它被称为 NP-complete:

Skiena, S. S. “Clique and Independent Set”和“Clique”。算法设计手册中的 §6.2.3 和 8.5.1。纽约:Springer-Verlag,第 144 和 312-314 页,1997 年。

因此,如果您想要一个高效的算法,您将不得不希望您的特定 isValidWith 函数具有比单纯的交换性更多的结构,并且您必须利用该结构。

针对您的具体问题,您应该能够做到以下几点:

  1. 按 x 坐标升序对点进行排序。
  2. 在排序列表中查找 y 坐标的longest decreasing subsequence

每个操作都可以在 O(n*log(n)) 时间内执行,因此您的特定问题可以有效地解决。

【讨论】:

  • 所以我想我会建立一个图,其中每个顶点代表一个数组元素,边连接通过 isValidWith 的对?
  • @Devsman 我在我的回答中添加了一个部分,讨论您的特定 isValidWith 函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
相关资源
最近更新 更多