用于检查两个数组是否相似的Java代码

时间:2017-04-25 12:57:52

标签: java arrays

我从网站上遇到了这个编码问题。问题如下:

  

如果可以通过交换其中一个数组中的至多一对元素从另一个数组中获得一个数组,则称这两个数组相似。

     

给定两个数组,检查它们是否相似。

     

实施例

     

对于A = [1,2,3]和B = [1,2,3],输出应为   areSimilar(A,B)= true。

     

数组相等,无需交换任何元素。

     

对于A = [1,2,3]和B = [2,1,3],输出应为   areSimilar(A,B)= true。

     

我们可以通过在B中交换2和1来从A获得B.

     

对于A = [1,2,2]和B = [2,1,1],输出应为   areSimilar(A,B)= false。

     

A或B中任何两个元素的任何交换都不会使A和B相等。

这是我给出的解决方案:

boolean areSimilar(int[] A, int[] B) {
    if(A.length != B.length) return false;

    int[] copyA = A, copyB = B;
    Arrays.sort(copyA); Arrays.sort(copyB); 
    int countSwap = 0;

    if(!Arrays.equals(copyA, copyB)) return false;

    for(int i = 0; i < A.length; i++) {
        if(A[i] != B[i]) countSwap++;
    }

    return (countSwap == 2 || countSwap == 0);
}

此代码为以下数组提供了正确的结果:

  1. 答:[1,2,3]
    B:[1,2,3]

  2. 答:[1,2,3]
    B:[2,1,3]

  3. 答:[1,2,2]
    B:[2,1,1]

  4. A:[1,1,4]
    B:[1,2,3]

  5. 答:[1,2,3]
    B:[1,10,2]

  6. A:[2,3,1]
    B:[1,3,2]

  7. 但每当我尝试提交代码时,网站仍显示“INCORRECT”。它无法通过六个隐藏测试中的两个,我无法弄清楚原因。这是正确的代码吗?还有其他更简单的方法吗?

3 个答案:

答案 0 :(得分:7)

您的代码无效,因为您在此处对原始数组进行了排序...

copyA = A, copyB = B;
Arrays.sort(copyA); Arrays.sort(copyB);

然后你要比较排序的数组而不是原始数组,以检查它们是否只能使用一个交换进行转换!!

你应该这样做......

boolean areSimilar(int[] A, int[] B) {
    if(A.length != B.length) return false;

    int countSwap = 0;
    int[] copyA = Arrays.copyOf(A, A.length);
    int[] copyB = Arrays.copyOf(B, B.length);

    // checking both contain the same elements...
    Arrays.sort(copyA); Arrays.sort(copyB); 
    if(!Arrays.equals(copyA, copyB)) return false; 

    // checking for min 2 swaps using original arrays...
    for(int i = 0; i < A.length; i++) {
        if(A[i] != B[i]) countSwap++;
    }

    return (countSwap == 2 || countSwap == 0);
}

更有效的解决方案......

boolean areSimilar(int[] A, int[] B) {
  ArrayList<Integer> ids = new ArrayList<>();
  for (int i = 0; i < A.length; i++) {
    if ( A[i] != B[i] ) {
      ids.add(i);
    }
  }
  if (ids.size() == 0) {
    return true;
  }
  if (ids.size() != 2) {
    return false;
  }
  int id1 = ids.get(0);
  int id2 = ids.get(1);
  if (A[id1] == B[id2] && A[id2] == B[id1]) {
    return true;
  }
  return false;
}

答案 1 :(得分:4)

程序中的问题

您没有创建和排序数组的副本,而是使用了赋值。

copyA = A

这意味着copyA仍然是对原始数组的引用,因此,当您尝试计算掉期时,原始数组将被排序。

这意味着当您尝试检查具有相同元素但交换次数很多的两个数组时,当您应该获得{{1}时,您将获得true }。

应该通过以下方式复制数组:

  • false
  • A.clone()
  • Arrays.copyOf(A, A.length)

设置而不是排序

您可以使用集合,而不是复制数组,排序和比较。排序的原因是检查两个数组是否具有完全相同的元素。在这种情况下,您可以将元素放入集合中并比较集合,而无需进行排序。

copyA = new int[A.length]; System.arrayCopy(A,0,copyA,0,A.length);

当且仅当两个集合包含完全相同的元素时,集合的Set<Integer> setA = new HashSet<>(Arrays.asList(A)); Set<Integer> setB = new HashSet<>(Arrays.asList(B)); if ( ! setA.equals(setB) ) { return false; } 方法才会返回equals。(顺序在集合中无关紧要)。

只有在保证数组不具有重复值时,set方法才有效。频率图可以用于重复的数组,但坦率地说,它是不可读的。

线性方法

除线性内存外,由于排序,您的方法需要O(n log n)。事实上,现在的问题可以在线性时间和恒定记忆中解决。

  • 检查长度是否相等。如果没有,请返回false。
  • true为两个元素的数组,用于存在差异的位置的索引。
  • 循环数组(就像你现在一样)计算差异。
  • 如果您遇到差异,请ind&lt; 2,将countSwap放入i,然后增加ind[countSwap]
  • 在循环结束时,如果countSwap为0,则返回true。
  • 如果countSwap为1或大于2,则返回false。
  • 如果countSwap为2,请检查您保留的索引处的项目。如果countSwapA[ind[0]] == B[ind[1]],则返回A[ind[1]] == B[ind[0]],否则返回true

<强>解释

如果两个数组之间存在1或3个及以上的差异,那么它们当然不是&#34;类似的&#34;。

但如果你确切地有2个差异,这可能是因为这两个地方有完全不同的值,或者因为有交换。

所以你检查这两个差异是否是因为交换。

无需排序。排序的唯一原因是查看两个数组是否具有完全相同的元素。但差异的数量可以告诉你没有排序。

顺便说一句,一旦false达到3,你就可以摆脱循环。

答案 2 :(得分:-3)

def areSimilar(a, b):
    n = 0
    if len(a)!=len(b):
        return False
    else:
        for i in range(len(a)):
            if a[i]!=b[i]:
                n+=1
                if n>2:
                    return False
            if a[i] not in b:
                return False
        print(n)
        return True