确定2D数组中的行是否唯一

时间:2014-12-09 21:33:59

标签: java arrays algorithm multidimensional-array

我试图创建一种算法,该算法确定2D整数数组中的所有行是否都是唯一的(即不相交)。目前,我有一个强力算法,它将每行中的每个值检查到其他行中的每个值,但我想加快速度。是否有某种分而治之的方法来处理这个问题?我在单个数组和列表中找到了一些半解决方案,但在2d数组中没有。

4 个答案:

答案 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。它是为这样的东西设计的:

http://www.geeksforgeeks.org/check-two-given-sets-disjoint/

启发的

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暗示。

我仍然希望对这些不同的方法进行基准测试。