如何对两个整数数组进行顺序不敏感比较

时间:2010-04-19 06:41:32

标签: java

我想要以这种方式比较的Java代码(例如):

<1 2 3 4>  = <3 1 2 4>
<1 2 3 4> != <3 4 1 1>

我不能使用hashmap表或任何东西;只是没有库的纯代码。

我知道有两种方法。

  1. 对它们进行排序并按索引比较数组索引
  2. 使用两个for循环并将外部索引与内部索引进行比较。我一直在努力,但仍然没有工作:

    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {   
            if(a[i] != a[j] && j == n)
                return false;
        }
    }
    return true;
    
  3. 代码有什么问题?感谢

8 个答案:

答案 0 :(得分:5)

排序&amp;相比。你无法更好地获得复杂性,而且你对速度所做的任何“改进”都会冒你的代码出错的风险。

[edit]实际上......如果你知道你的数字相对较小(比如说:数组只包含0到1000之间的数字),O(n)中有另一种选择。这样的事情(抱歉,如果语法错误,我最近没有使用java):

int count[1001]; // already intialized to 0

for(int i=0;i<n;i++){ count[a[i]]++; count[b[i]]--;}
bool arrays_identical = true;
for(int i=0;i<=1000 && arrays_identical; i++)
    arrays_identical &= count[i]==0;

免责声明:此代码不包含“健全性检查”(即数组实际上长度为“n”,数字在规定的时间间隔内) - 这只是为了说明原则。

答案 1 :(得分:3)

Arrays.sort(a);
Arrays.sort(b);
return Arrays.equals(a, b);

答案 2 :(得分:2)

由于这是家庭作业,我猜想一个简单的二次解决方案(你最初的尝试是),很好。在这种情况下,你可以这样做:

int count(int[] nums, int x) {
    int count = 0;
    for (int num : nums) {
        if (num == x) count++;
    }
    return count;
}   
boolean equals(int[] arr1, int[] arr2) {
    if (arr1.length != arr2.length) return false;
    for (int x : arr1) {
        if (count(arr1, x) != count(arr2, x)) return false;
    }
    return true;
}

为了清晰起见,这就牺牲了速度:它显然是正确的

提示

  • 适用时,每次使用;它总是读取更好的可读性
  • 帮助程序功能提高了可读性和可重用性!

答案 3 :(得分:1)

我认为在进行任何迭代之前检查两个数组的长度是否相等是明智的。这是一种选择退出早期努力工作的廉价方式,它为您提到的第二种方法修复了以下类型的失败:

{1, 2, 3}被视为等于{4, 3, 2, 1}

答案 4 :(得分:1)

这是一个O(n ^ 2)问题。没有其他解决方案比直接比较两个阵列更快。

Virgil的解决方案很酷,除了它不是真正的O(n)性能。它实际上是O(n + 1000)性能。第二次设置布尔变量的数组比较是昂贵的,并且在小数组中适得其反。

你写的解决方案除了bug之外是最好的。

以下是错误更正版本。

boolean[] matchedPositions = new boolean[n];
for(int k = 0; k < n; k++
{
    matchedPositions[k] = false;
}

for(int i = 0; i < n; i++)
{
    for(int j = 0; j < n; j++)
    {   
        if(matchedPositions[j] == false && a[i] == a[j])
        {
             matchedPositions[j] = true;
             break;
        }

        if(j == n - 1)
        {
            return false;
        }
    }
}
return true;

在这种情况下,如果整数匹配,则内部循环将中断并设置或标记匹配的位置。这对于具有重复条目的数组是必需的,这将避免左数组中的两个条目与右数组中的一个条目匹配。

如果匹配没有发生,由 j == n - 1 标识,则返回false。

由于我们期望布尔值中的默认值为false,因此最好标记初始化

实际上,该解决方案具有O(n log n + n)性能损失。排序和比较也具有O(n ^ 2 + n)的性能损失。 Sort具有O(n ^ 2)性能和一个用于检查的循环。但排序会改变数组的内容,但事实并非如此。

答案 5 :(得分:0)

以下是您发布的代码的修复程序。

for(int i = 0; i < n; i++)
{
    int j;
    for(j = 0; j < n; j++)
    {   
        if(a[i] == b[j]) break;
    }
    if (j == n) return false;
}
return true;

然而,对于包含重复项的数组,该算法将完成。例如,数组{1, 1, 2, 3}将与数组{1, 2, 2, 3}匹配。

我强烈建议您实施排序和比较算法。

答案 6 :(得分:0)

如果你把一个数组作为1,2,3,4,3,1,2,4那么解决方案是这样的。

2n =整数总数:8

//program
int i, j, n = 4;
for(i = 0; i < n; i++)
  for(j = n; j < 2n; j++)
   {
     if( a[i] != a[j])
      { 
        j++;
      }
     else
     {
       i++; exit();
     }
  }  

if (i == n) 
{ //They both are equal;
}
else if(i != n)
{
//They both are not equal;
}

如果不能正常工作,请对其进行评论。 谢谢。

答案 7 :(得分:0)

在实际启动计算复杂度更高的解决方案之前,您可以运行快速O(n)测试以查看阵列是否相同。有时这会导致误报,并且您可以使用更多计算密集型手段进一步调查。如果返回false,则可以确保数组不同。

基本方法是在两个数组的第i个元素之间进行累积异或。如果得到的XOR非零,那么您就知道两个数组是不同的。如果XOR为零,它们可能是相同的,但需要做更多的工作来确认。

int c_xor = 0;  // XOR accumulator

for (int i = 0; i < n; ++i)
    c_xor ^= arr1[i] ^ arr2[i];

// They're different if c_xor != 0; the might be the same if c_xor == 0
return c_xor == 0;