【问题标题】:Checking two int arrays for equality - Regardless of order检查两个 int 数组是否相等 - 无论顺序如何
【发布时间】:2013-10-12 17:57:16
【问题描述】:

免责声明:这是作业,所以请不要只给我代码,我想解释一下如何用尽可能少的实际代码来做这件事。

所以我有两个未排序且长度相等的整数数组,并且可以包含重复值。由于这是家庭作业,有一个奇怪的情况是我不允许使用 java.utils 中的任何内容或对数组进行排序。

我应该检查两个数组是否包含相同的元素,而不管顺序如何。因此比较数组 [5, 6, 7, 5, 6, 3] 和 [6, 6, 7, 5, 5, 3] 将返回 true,同时比较 [7,7 8] 和 [7, 8, 8 ] 不会。

我不知道如何做到这一点,我已经搜索了问题,但它们似乎都使用了 java.utils 中的某些东西,或者数组不包含重复项。我尝试循环遍历第一个数组中的每个值,并为每个值循环遍历第二个数组,检查该值是否存在于那里,但它会因重复而出错。

如果能在正确的方向上提供任何形式的帮助、建议或提示,我将不胜感激。谢谢!

【问题讨论】:

  • 数组中可以包含的数字范围是否有限制?还是他们只是随意的ints?
  • 这将是相对较短的数组,因此无需担心性能。但是是的,否则是任意的 int s。

标签: java arrays equals


【解决方案1】:

如何依次从第一个 int 数组中取出每个元素,然后检查是否在第二个 int 数组中找到它。为了实现这个想法,您需要创建一个布尔值数组,这些值都初始化为false,以指示是否使用了第二个 int 数组中的值。然后当你从第一个数组中找到每个值时,将布尔数组中的对应元素设置为true

【讨论】:

  • 如何检查第一个数组中的数字在两个数组中出现的次数是否相同?
  • 对于第一个 int 数组中的每个元素,一旦它在布尔数组中将 false 更改为 true,它不应再检查任何值,并从下一个元素重新开始在 int 数组中。这样,如果 int 数组中的每个元素都对应于布尔数组中的更改,则整个数组将只有 true
【解决方案2】:

一种方法是遍历第一个数组并删除与第二个数组中相同的元素。

当您在第二个数组中未能从第一个数组中找到元素时,则数组不相等。当您从第二个数组中的第一个数组中找到最后一个元素时,这些数组是相等的。

如果不修改数组,那么您必须先克隆您更改的数组。

【讨论】:

    【解决方案3】:

    这是一个解决方案,在较长的数组上可能会变慢,因为它是 O(n²)

    // return how often n appears in an array
    public static int count(int n, int[] array) { ... }
    
    public static boolean equalarrays(int[] arr1, int[] arr2) {
       for (int i: arr1) {
           if (count(i, arr1) != count(i, arr2)) return false;
       }
       return arr1.length == arr2.length;
    }
    

    【讨论】:

      【解决方案4】:
      1   public static boolean compare(int[] a, int[] b)
      2   {
      3       if(a.length != b.length) return false;
      4
      5       aloop:for(int i = 0; i < a.length; ++i)
      6       {
      7           bloop:for(int j = 0; j < b.length; ++j)
      8           {
      9               if(a[i] == b[j])
      10              {
      11                  for(int k = j; k < i; ++k)
      12                  {
      13                      if(a[k] == b[j])    continue bloop;
      14                  }
      15
      16                  continue aloop;
      17              }
      18          }
      19
      20          return false;
      21      }
      22
      23      return true;
      24  }
      

      这基本上是说:取两个相同大小的数组 (3) ab,迭代槽 a (5),迭代槽 @ 987654325@ (7),将a 的元素与b 的每个元素进行比较(9),如果b 的任何元素等于a 的元素:

      • 如果为真:检查a 的这个元素是否已经处理过迭代a-loop 的索引(11) 并与已经处理过的元素进行比较(13) .
        • 如果为真:获取b 的下一个元素并重复。 (13)
        • 如果为假:获取a 的下一个元素并重复。 (17)
      • 如果为假:那么,当b 的元素不等于a 的元素时返回假(18)

      如果我们到达 (23) 行,b 的所有元素都是 a 的元素。返回真。

      编辑:此外,您可以反转 aloop 和 bloop 以获得一些额外的性能。 (我没有把它放到主代码块中,因为它容易混淆。)

      bloop:for(int j = 0; j < b.length; ++j)
      // could be written as
      bloop:for(int j = b.length; (--j) >= 0; )
      // which is faster as the comparison and incrementation step are merged into one
      

      【讨论】:

      • 它肯定比 Ingo 的版本快,因为这不一定会比较 a 的每个元素与 b 的每个元素,因为 continue 会跳过。我无法将它与接受的答案进行比较,因为我可能无法想到最佳实现,并且作者没有提到这种方法所必需的健全性检查。接受答案的字面实现不会返回有效结果。
      【解决方案5】:

      这是一个有趣的活动,我会在自己的时间做。我建议让两个 ArrayList 包含两个数组表的所有值。我这样做是因为您可以使用remove() 方法。循环遍历给定的第一个数组的所有元素。那将是您的参考数组。在参考数组的第一次迭代中获取对象。然后检查您的其他阵列是否 已经包含它。如果没有,则检查失败,您可以当场返回false,如果确实如此:删除它然后获取参考数组的下一次迭代。

      即使您不想要该代码,它也位于 pastebin 中:http://www.pastebin.com/3BEV2CqH 它接受Object[] ... tables 参数并使用equals 方法进行比较。如果你能像我一样成功,我相信你的老师会感到惊讶。

      【讨论】:

        【解决方案6】:

        一个简单的解决方案是复制两个数组,然后对副本进行排序和比较。这是O(NlogN),如果您使用良好的排序算法。如果你使用正确的库方法,你可以用大约 3 行代码编写它。

        @Andy256 和@Stochastically 的解决方案都应该有效,但它们都是O(N^2)

        【讨论】:

        • 但由于某种原因,问题说该解决方案不允许使用排序。
        【解决方案7】:

        一种常见的通用方法是对两个数组进行排序,然后进行比较。对于任何两个数组,这种方法总是会在可预测的时间内成功。我不认为有任何算法的最坏情况时间会比排序数组所需的时间好得多。

        然而,在许多情况下,拥有一种“通常”比排序数组更快的方法可能会很有用。举个简单的例子,假设对于每个整数 X,计算 (X*(X+123456)),并将这些值的总和相加(作为 long)如果两个列表包含相同的值,则以任意顺序,它们的总和应该相等。列表可能包含不同的值,但仍产生相同的总和,但在大多数情况下,如果列表包含不同的值,它们的总和可以被识别为不同,而无需经历对列表进行排序的麻烦。

        您可能需要考虑“哈希基数排序”的另一件事。基数排序的工作原理是让每遍将事物分成桶,然后输出第一个桶的内容,然后输出第二个、第三个、第四个、第五个桶的内容。打孔卡过去以这种方式分类,使用一台机器检查每张卡上的一列,然后根据打孔的内容将每张卡放入 13 个桶中的一个。可以使用 2^32 个桶的一次遍历、65,536 个桶的两次遍历、256 个桶的四次遍历等对任意数量的 32 位整数进行排序。不过,基数排序的一个小麻烦是,事物的分布各种桶通常会严重倾斜。如果一个人定义了一个函数,它将输入值映射到例如从 0 到 255 的数字,这样 1/256 的输入将被分配给每个值,那么可以在线性时间内将“排序”列表的任务减少为对 256 个列表进行排序的任务,每个列表的大小为 1/256 .请注意,生成的序列不会按传统意义上“排序”,但包含相同项目的两个列表将以相同的方式“排序”。

        【讨论】:

          【解决方案8】:

          这里有一个解决方案。反正这个帖子太旧了

          public static boolean equality(int[] list,int[] list2)
            {
              boolean result = false;
              int correct = 0;
              if(list.length == list2.length)
              {
                for(int i = 0; i< list.length; i++)
                {
                  for(int j = 0; j < list2.length; j++)
                  {
                    if(list[i] == list2[j])
                    {
                      correct++;
                      if(correct == list.length && correct == list2.length)
                      {
                        result = true;
                      }
                    }
                  }
                }
              }
              return result;
            }
          }
          

          【讨论】:

            猜你喜欢
            • 2017-04-25
            • 2020-02-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-15
            • 1970-01-01
            相关资源
            最近更新 更多