我试图创建一种算法,该算法确定2D整数数组中的所有行是否都是唯一的(即不相交)。目前,我有一个强力算法,它将每行中的每个值检查到其他行中的每个值,但我想加快速度。是否有某种分而治之的方法来处理这个问题?我在单个数组和列表中找到了一些半解决方案,但在2d数组中没有。
答案 0 :(得分:0)
如果要检查是否有两行包含相同的数字,可以将所有数字及其所属的行数放入一个长列表中。然后对此列表进行排序,这将使所有相同的数字彼此相邻。您可以轻松地确定每个相同数字的群集是否最初属于同一行。
如果你的表是n×m,算法将在 O ( nm ×(log( n )+ log(<)中运行EM>米)))。
答案 1 :(得分:0)
要测试任何两行是否是不相交的**,请创建两个集合(如java集拒绝重复,并在几乎O(1)时间内完成),每行一个并计算每个行的元素。
如果出现以下情况,则两行不相交:
count(rowASet) + count(rowBSet) == count( union(rowASet, rowBSet) )
这表明了一种2D阵列的算法,其中行连续地(作为集合)添加到运行的总集合中。在添加每行集合之前和之后测量总集合的计数。如果该计数增加了刚刚添加的行集的大小,那么刚添加的行与目前添加的行不相交。
**查看与@CandiedOrange的对话。我正在采取&#34;不相交的行&#34;表示在任何其他行中不包含任何元素的行,但可能在内部包含重复的元素。
答案 2 :(得分:0)
如果允许使用java集合,请考虑使用java的HashSet
。它是为这样的东西设计的:
areDisjoint()
import java.util.*;
public static void main (String[] args)
{
int[][] twoD = {{3,3,3},{4,4,4},{5,5,5}};
if ( disjointRows(twoD) )
{
System.out.println("Mutually disjoint rows");
}
else
{
System.out.println("Some element duplicated in other row");
}
}
public static boolean disjointRows(int[][] twoD)
{
// -- Copy 2D array into data structure -- //
ArrayList<HashSet<Integer>> rows = new ArrayList<HashSet<Integer>>();
for (int[] row : twoD)
{
HashSet<Integer> hs = new HashSet<Integer>();
for (int elem : row)
{
hs.add(elem);
}
rows.add( hs );
}
// Above is O = r*c time just as it would be to copy the 2D array.
// or you can express it as O(n^2)
// -- Mutual disjoint rows test -- //
// Compare every combination of rows
for (int y=1; y< rows.size(); y++)
{
for (int x=0; x<y; x++)
{
//TODO remove debugging code
System.out.print(areDisjoint( rows.get(x), rows.get(y) ) );
System.out.print("=");
System.out.print("(" + x + "," + y + ") ");
if (! areDisjoint( rows.get(x), rows.get(y) ) )
{
return false;
}
}
System.out.println("");
}
return true;
//Above is O = r(r-1)/2 * c
//or you can express it as O(n^3)
}
static boolean areDisjoint(Set<Integer> set1, Set<Integer> set2)
{
//set1 must not contain anything in set2
for (int i : set2)
{
if ( set1.contains(i) )
return false;
}
return true;
// Above is c or O(n) because contains lookup is O(1)
}
<强>输出:强>
// true =(0,1)
// true =(0,2)true =(1,2)
//完全不相交的行
我不知道这是否比你的“暴力”解决方案更好,因为你没有发布它。
从O大概念的角度来看,我可以通过japreiss的解决方案来判断这是颈部和颈部。我们都在O(n ^ 3)。此解决方案使用更多内存,因为它复制2D阵列而不是改变它。当性能相同时,我强烈建议您根据可读性选择算法。我承认我的时间更长。我花时间对它发表评论。
另请参阅:Is a Java hashmap really O(1)?
// If each row is to be disjoint from all other rows then
// then testing them all against each other would produce
// this truth table.
//
// 0 1 2
// |----|----|----|
// 0 | F | T | T |
// |----|----|----|
// 1 | T | F | T |
// |----|----|----|
// 2 | T | T | F |
// |----|----|----|
//
// Testing a row against it self can be ignored as can
// tests that simply transpose the input rows. Leaving us with
//
// 0 1 2
// |
// 0 |
// |----|
// 1 | T |
// |----|----|
// 2 | T | T |
// |----|----|
//
// So long as that's true, the rows are mutually disjoint
答案 3 :(得分:0)
在我发布之后,我想到了2个更快的算法,但结果却是Danylo Mysak的回答和“运行总计”danh暗示。
我仍然希望对这些不同的方法进行基准测试。