【问题标题】:Find similar rows in 3 two-dimensional arrays在 3 个二维数组中查找相似的行
【发布时间】:2012-01-09 11:52:09
【问题描述】:

在 Java 中解决以下问题的最佳方法是什么? 有 3 个二维数组,它们的行数和列数相等:

Array1:
[1]: {1, 2, 3}
[2]: {2, 2, 4}
[3]: {1, 1, 1}

Array2:
[1]: {1, 2, 0}
[2]: {1, 2, 3}
[3]: {1, 0, 1}

Array3:
[1]: {1, 1, 1}
[2]: {1, 2, 3}
[3]: {1, 0, 1}

我需要找出所有数组中存在的行索引。在上面的例子中,答案应该是:[1],[2],[2]

数组1 [1]:{1、2、3}

数组2: [2]:{1、2、3}

数组3: [2]:{1、2、3}

更新:是否有任何内置函数可以做到这一点?还是 FOR 循环是唯一的解决方案?

【问题讨论】:

    标签: java arrays multidimensional-array


    【解决方案1】:

    我会做以下事情:

    • 创建一个在数组中取一行并实现hashcodeequals 的类。
    • 将前两个数组中的每一行(包装在上述类中)插入两个HashMaps
    • 对于最后一个数组中的每一行,确定它们是否存在于HashMaps

    编辑 #2,意识到映射需要反转。

    private Map<MyClass, Integer> map(int[] array){
      Map<MyClass, Integer> arrayMap = new HashMap<>();
      for (int i; i<array.length; i++)
            arrayMap.put(new MyClass(array[i]), i);
    }
    
    private mySearch(){
       int[] array1, array2, array3;
    
       Map<MyClass, Integer> map1 = map(array1);
       Map<MyClass, Integer> map2 = map(array2);
    
       for (int i=0; i<array3.lenght; i++){
          MyClass row = new MyClass(array3[i]);
          Integer array1Row = map1.get(row);
          Integer array2Row = map2.get(row);
    
          if (array1Row != null && array2Row != null){
             // Matching rows found
          }
       }
    }
    

    【讨论】:

    • 能否举个第二步的例子?
    【解决方案2】:

    AFAIK 没有内置函数。

    您需要编写自己的函数来实现它(使用for 循环)。

    发布一些代码以显示您尝试了什么,如果它不能正常工作或进行优化。

    【讨论】:

      【解决方案3】:

      检查此代码:

      ArrayList<Integer[]> arr1 = new ArrayList<Integer[]>();
          arr1.add(new Integer[]{1,2,3});
          arr1.add(new Integer[]{2,2,5});
          arr1.add(new Integer[]{1,1,1});
      
          ArrayList<Integer[]> arr2 = new ArrayList<Integer[]>();
          arr2.add(new Integer[]{1,2,0});
          arr2.add(new Integer[]{1,2,3});
          arr2.add(new Integer[]{1,0,1});
      
          ArrayList<Integer[]> arr3 = new ArrayList<Integer[]>();
          arr3.add(new Integer[]{1,1,1});
          arr3.add(new Integer[]{1,2,3});
          arr3.add(new Integer[]{1,0,1});
      
      
          for (int r = 0 ; r < arr1.length() ; r++) {
              for(int s = 0 ; s < arr2.length() ; s++){
                  for(int t = 0 ; t < arr3.length() ; t++){
                      if(Arrays.deepEquals(arr1.get(r), arr2.get(s))){
      
                      }else
                      {
                          continue;
                      }
                      if(Arrays.deepEquals(arr1.get(r), arr3.get(t))){
                          System.out.println(r + " " + s + " " +t);;  
                      }
                  }
      
              }
          }
      

      【讨论】:

      • 如果每个数组的行数不同,会不会起作用?
      • 还有,如果数组的个数大于3,会起作用吗?
      • 它将适用于数组中的任意数量的行,只需更新循环索引。但是,这是 O(n^3) 可能的效率最低的解决方案。 Mike 的解决方案至少比这更有效。我认为哈希解决方案更好。
      【解决方案4】:

      首先,编写一个名为AreRowsEqual() 的函数,用于比较两行。所以,现在,这个问题被重述为Find similar elements in 3 arrays

      其次,根据先验知识,试着想出一个最接近你已经知道的解决方案:要在两个数组中找到相等的元素,你需要一个双嵌套的 for 循环。所以,要在三个数组中找到相等的元素,你需要一个三重嵌套循环,对吧?

      好的,现在,把它作为一个糟糕的、糟糕的、糟糕的解决方案划掉,因为它的时间复杂度是 O(n^3)。我们应该可以做得更好。

      考虑一下:为了让一个元素在所有 3 个数组中都相似,首先它必须在前两个数组中相似;然后,它必须在接下来的两个中相似。这种算法的复杂性类似于 O(x*n),其中 x 是数组的数量。好多了,对吧? (我无法准确地弄清楚 O() 将是什么,对任何人有帮助吗?)编辑: 结果是 O((n^2)*(x-1)),这是一个当 n > x --END EDIT 时比 O(n^3) 好很多,顺便说一句,这可以让您忘记严格的 3 数组的要求,只需考虑一些 x数组。

      我写了一个方法,得到了一个赞成,然后我意识到它不起作用,我删除了它。这是另一个尝试,我相信它会奏效:

      创建一个二维整数数组。我们将其称为“矩阵”。该矩阵将有x 列,行数将是您的第一个数组的行数。 (是的,即使您的数组具有不同的长度,这也会起作用。)该矩阵的单元格中的数字将匹配行索引。因此,例如,在我描述的算法完成后,矩阵中的一行{ 1, 3, 2 } 将告诉我们第一个数组的第 1 行与第二个数组的第 3 行和第三个数组的第 2 行匹配。我们将使用-1 表示“不匹配”。

      因此,矩阵的第一列需要使用第一个数组的所有行的索引进行初始化,即使用数字0, 1, 2, ... n,其中n 是第一个数组中的元素数。

      对于每个额外的数组,在矩阵中填充它的列如下:循环遍历矩阵中当前列的每一行,并计算单元格如下:如果前一列的对应单元格是-1,则进位-1 进入这个单元格。否则,在当前数组中查找与前一个数组的对应行匹配的行,如果找到,将其索引存储到此单元格中。否则,将 -1 存储在此单元格中。

      对所有数组重复,即对矩阵中的所有列重复。最后,您的匹配行是那些在矩阵的最后一列中没有-1 的行。

      如果您真的关心效率,您可以按照 John B 的建议进行操作,并编写一个名为 Row 的不可变类,它封装(包含引用)一行并实现 hashCode()equals()equals() 这里可以使用Arrays.deepEquals() 来实现。 Arrays 中可能还有一些名为 deepHashCode() 的好东西,否则你需要自己动手。

      【讨论】:

      • 如果数组的行数不同,解会不会差不多?
      • -1 前两个数组的比较时间为 O(n^2),因此总时间将大于建议的 O(x*n) 时间。
      • 我写了一个方法,收到了一个赞成票,然后我意识到它不起作用,我删除了它。我现在发布了另一个尝试,我相信它会起作用。
      • @JohnB 我更新了我的答案。我之前的回答也许值得一票否决,因为它不起作用,但不是因为这样一个微小的细节,因为它错误地估计了它的大哦会是什么。我提出的算法肯定比 O(n^3) 更好。我仍然无法确切地知道它的大哦是什么,所以请随时帮我弄清楚。
      • @MikeNakis 删除了反对票。在最坏的情况下(第一个 x-1 数组的所有行都匹配),上面将是 O(n^3)。实际性能取决于每个阵列的匹配数。恕我直言,散列解决方案更简单、更高效,因此我很感激参考。
      【解决方案5】:
      1. 编写一个接受两个参数的方法:要搜索的二维数组,一维数组行。如果没有找到匹配,该方法返回 -1,否则返回匹配行的索引。

      2. 对于第一个数组的每一行: 2a.调用从第一个数组和 Array2 传递行的方法。 2b。如果2a返回>0,调用传递同一行和Array3的方法

      3. 如果2b返回>0,则输出返回的索引。

      【讨论】:

      • 两个问题:第一个应该是&gt;=0。其次,这是低效的,如果不接近 O(n^3),至少也是 O(n^2)。如果数组 1 中的每一行都存在数组 3,那么这将是 O(n^3)。哈希是一个更好的选择恕我直言。
      【解决方案6】:

      检查Arrays.deepEquals() 方法。它会检查两个数组是否相等。

      【讨论】:

      • 这是确定匹配的好方法,但算法会是 O(n^2)
      • 不,这不起作用,因为不能保证行的顺序相同。一个数组中的行 [1] 可能与另一个数组中的行 [2] 匹配,但deepEquals() 不会将其视为匹配。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-03
      • 2021-03-03
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      相关资源
      最近更新 更多