4

我有一组包含相同数量的数字的 2 个 int 数组

例如

int[] array1 = {1,3,5,5,2}
int[] array2 = {5,3,4,4,4}

我需要根据 2 个标准来比较它们

  1. 有多少元素在同一个索引上有相同的值
  2. 有多少元素在不同的索引上具有相同的值

并返回一个表示值的整数数组

我有几个例子,以便您更好地理解:

   int[] array0 = {1,3,5,5,2};
   int[] array1 = {5,3,4,4,4};
   int[] array2 = {5,3,4,4,5};
   int[] array3 = {2,3,2,2,4};
   int[] array4 = {5,5,2,1,3};
   int[] array5 = {3,1,5,5,2};
   int[] array6 = {1,3,5,5,2};

   compare(array0,array1); //this would return 1,1
   compare(array0,array2); //this would return 1,2
   compare(array0,array3); //this would return 1,1
   compare(array0,array4); //this would return 0,5
   compare(array0,array5); //this would return 3,2
   compare(array0,array6); //this would return 5,0

对于第一个数字很简单,我只需要检查 array1 的索引 i 上的元素是否与 array2 中的相同。

我在生成第二个数字时遇到问题,因为应该采用其中一个数组中的最小数字。如果我只看 array1 的元素是否在 array2 的某个地方,它在某些情况下会产生错误的结果。

如果你看

int[] array1 = {1,3,5,5,2}

int[] array3 = {2,3,2,2,4};

并检查 array1 在索引上是否与 array3 具有相同的内容,它会返回 3 个数字相等但在不同的位置,这是错误的,因为它应该从最小的数字判断,结果应该是 1。

如果我切换它来比较 array3 在某个索引上是否与 array1 具有相同的内容,它适用于这种情况,但不适用于其他情况。

关于如何解决这个问题的任何想法,我很无能?

4

7 回答 7

1
  • 克隆两个输入整数数组。

  • 检查并查看元素在同一索引上是否具有相同的值。

  • 如果是这样,将 1 添加到相同的索引计数器并将输入整数数组中的值更改为 -1(或小于最小有效值的数字)。

  • 使用嵌套的 for 循环检查元素是否具有相同的值。换句话说,检查第一个整数数组的第一个元素和第二个整数数组的所有元素。跳过两个数组中具有相同索引的元素,并跳过小于最小有效值的元素。

  • 如果是这样,将 1 添加到不同的索引计数器并将输入整数数组中的值更改为 -1(或小于最小有效值的数字)。

于 2012-11-07T19:39:31.453 回答
0

您需要将所有数组转置为树状结构,该结构基本上将索引所有数组中的所有唯一值,并存储指向它们在数组中的位置和哪个数组的指针。该树的基本蓝图结构将是:

uniqElemVal->arrayIndx->arrayID = true

其中 uniqElemVal 将是 1,3,5,2 代表 1,3,5,5,2,2,3,4 代表 2,3,2,2,4 等,所有工会

arrayIndx 将是第一个数组 0 中的 1,对于 5 将是 2 和 3 等。

数组 ID 是任意的,可让您键入每个数组,例如第一个为 1,第二个为 2,等等。

所以在这种情况下:

#1st array
1->0->1
3->1->1
5->2->1
5->3->1
2->4->1

#2nd array
2->0->2    
3->1->2 
3->2->2
2->3->2
2->4->2
4->5->2

然后,当您遍历这棵树时,只要您有一个具有超过 1 个叶子的 2 级节点,这意味着该特定元素值在多个数组的特定位置存在匹配。

我个人将这棵树定义为

HashMap<Integer, HashMap<Integer, ArrayList<Integer>>>

因此,只要您有一个具有 >1 个元素的叶数组列表,就意味着您有一个匹配项

于 2012-11-07T19:46:21.453 回答
0

首先,这听起来是一个非常糟糕的主意。不要返回一个数组,其中每个索引都意味着不同的和神秘的东西。制作两个方法:compareSameIndex(array, array) 和 compareDifferentIndex(array, array)。

对于这些方法的实际实现,您可以检查第一个数组中的每个索引以查看它们是否出现在第二个数组中的任何位置并调用它只是 compare()。然后 compareDifferentIndex() 变成 compare()-compareSameIndex()。例如:

public int compare (int[] array0, int[] array1) {
  int matches = 0;
  List<Integer> list1 = Arrays.asList(array1);

  for (int curInt : array0) {
    if (list1.contains(curInt)) {
      matches++;
    }
  }
  return matches;
}

public int compareSameIndex(int[] array0, int[] array1) {
  int matches = 0;
  for (int i=0; i < array0.length; i++) {
    if (array0[i] == array1[i]) {
      matches++
    }
  }
  return matches;
}

public int compareDifferentIndex(int[] array0, int[] array1) {
  return compare(array0, array1) - compareSameIndex(array0, array1);
}

当相同的数字出现两次时,要求似乎有点模糊,但您可以将该逻辑构建到 compare() 中以适应。您也可以针对非常大的数组进行优化,在这些数组中您不会两次检查相同的数字,但这将是我将采用的一般方法。

于 2012-11-07T19:48:00.340 回答
0

也许对于第二种情况,您可以尝试从数组中删除数字并在发现它们匹配后退出循环。您可以将临时数组设置为原始数组的值。然后对照 中的array1[0]所有值检查 的值array3。找到匹配项后,从两个数组中删除数字并array1[1]检查array3.

因此,当您检查array1[4]array3[0],您将得到匹配。然后您将删除这两个数字并跳出循环。没有更多数字要签入array1,因此结果将为 1。

我认为这将解决两次计算相同值的问题。

于 2012-11-07T19:39:59.190 回答
0

你可以有一个已经访问过数字的集合。你会喜欢:(不测试这段代码是否运行,只是给你一个想法)

public int[] compare(int[] first, int[] second) {
     Set<Integer> numbersFoundInFirstArray = new LinkedHashSet<Integer>();
     Set<Integer> numbersFoundInSecondArray = new LinkedHashSet<Integer>();
     int inSameIndex = 0;
     int inDifferentIndex = 0;

     for (int i; i < first.length; i++) {
         if (first[i] == second[i]) {
             inSameIndex++;
         }
         if (numbersFoundInFirstArray.contains(second[i])) {
             inDifferentIndex++;
         }
         if (numbersFoundInSecondArray.contains(first[i])) {
             inDifferentIndex++;
         }
         numbersFoundInFirstArray.add(first[i]);
         numbersFoundInSecondArray.add(second[i]);
     }
     return new int[] {inSameIndex, inDifferentIndex};
}

如果我记得清楚,集合中的包含比较有 O(1)。Set 的属性是您将只有一个特定类型的元素。所以,如果你加 1 两次,它将只有一个 1 的引用。这样,你将只测试当前数字是否已经在另一个数组中找到:)

于 2012-11-07T19:43:18.863 回答
0

This should do the trick:

public void compare(int[] arrayA, int[] arrayB) {
    int sameIndex = 0;
    int diffIndex = 0;
    //Made two new empty arrays to save the status of each element in the corresponding array, whether it has been checked our not, if not, it'd be null.
    String[] arrayAstatus = new String[arrayA.length];
    String[] arrayBstatus = new String[arrayB.length];
    for (int i = 0; i < arrayA.length; i++) {            
        if (arrayA[i] == arrayB[i] || arrayAstatus[i] != null) {
            sameIndex++;
            continue;
        }
        for (int a = 0; a < arrayB.length; a++) {
            if (a == i || arrayBstatus[a] != null) {
                continue;
            }
            if (arrayA[i] == arrayB[a]) {
                arrayAstatus[i] = "checked";
                arrayBstatus[a] = "checked";
                diffIndex++;
                break;
            }
        }
    }
    System.out.println(sameIndex + ", " + diffIndex);
}
于 2012-11-07T20:40:45.183 回答
0

检查参数只是一个好习惯。可能有一些小的优化可以在这里完成,但是哈希可以让你存储你已经访问过的位置,以便不再计算它们一次。

 private int[] compare(int[] arr1, int[] arr2){
    int same_index = 0;
    Hashtable differences = new Hashtable();
    int diff_count = 0;
    if (arr1.length != arr2.length){
        throw new IllegalArgumentException("Array Size is not identical.");
    } else {
       for(int count = 0; count < arr1.length; count++){
          if (arr1[count] == arr2[count]{
              same_index++;
              differences.put(count, null);
          } else {
              for (int count2 = 0; count2 < arr1.length; count2++){
                  if(!differences.containsKey(count2) && arr1[count] == arr2[count2]){
                      differences.put(count2, null);
                      diff_count++;
                  }

              }                  
          }
       }
    }
    int[] returnArray = new int[2];
    returnArray[0] = same_count;
    returnArray[1] = diff_count;
    return (returnArray);
 }
于 2012-11-07T19:52:33.043 回答