Dev*_*man 0 algorithm search subset
我希望这不是一个统计问题......
假设我有一个界面:
public interface PairValidatable<T>
{
public boolean isValidWith(T);
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我有一个大型的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;
}
}
Run Code Online (Sandbox Code Playgroud)
直观的想法是保持一个点向量,添加数组元素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);
Run Code Online (Sandbox Code Playgroud)
如上所述迭代将为我们提供仅包含元素0的子集,但是元素1,2和4的子集是更大的子集,其中每对通过验证.然后算法应该返回存储在元素1,2和4中的点.虽然元素3和4彼此有效并且元素1和4彼此有效,但元素2和3不是,元素1和3也不是.包含1,2和4的子集是比3和4更大的子集.
我猜想一些树或图算法最适合解决这个问题,但我不知道如何设置它.
该解决方案不必是特定于Java的,并且最好可以用任何语言实现,而不是依赖于Java内置函数.出于熟悉的原因,我刚才使用了类似Java的伪代码.
大概isValidWith是可交换的 - 也就是说,如果x.isValidWith(y)那么y.isValidWith(x).如果您只知道这一点,那么您就拥有了一个最大团队问题的实例,这个问题已知为NP-complete:
Skiena,SS"Clique and Independent Set"和"Clique".算法设计手册中的§6.2.3和8.5.1.纽约:Springer-Verlag,第144和312-314页,1997年.
因此,如果你想要一个有效的算法,你将不得不希望你的特定isValidWith函数具有更多的结构而不仅仅是交换性,你将不得不利用这种结构.
对于您的具体问题,您应该能够执行以下操作:
每个操作都可以在O(n*log(n))时间内执行,因此您的特定问题可以有效解决.