【问题标题】:Best Algorithm for getting non duplicate from two arrays从两个数组中获取非重复的最佳算法
【发布时间】:2015-03-24 13:31:07
【问题描述】:

问题:从两个给定数组(不是排序数组)中找到不重复的项目。如果第一个数组是 {1, 2, 3} 而第二个数组有 {2, 3, 4} 那么结果应该是 {1,4}。

我做了什么:我通过使用 Set 实现了它。但似乎 O(n2)。

我需要什么:是否有任何其他算法可以编写得更优化?

我的代码:

package src;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.TreeSet;

public class GetNonDuplicate {

    public static void main(String[] args) {

        Integer[] arrayOne = {1, 2, 3};
        Integer[] arrayTwo = {2, 3, 4};
        List<Integer> resultList = new ArrayList<Integer>();

        List<Integer> listOfArrayOne =  new ArrayList<Integer>(Arrays.asList(arrayOne));
        TreeSet<Integer> setOne = new TreeSet<Integer>(listOfArrayOne);
        System.out.println("SetOne is : " + setOne);

        for (Integer elem2 : arrayTwo) {

            boolean exists = setOne.add(elem2);
            System.out.println("For elem2 [" + elem2 + "], exists [" + exists + "]." );
            if (exists) {
                resultList.add(elem2);
            }
        }

        System.out.println(resultList);

        List<Integer> listOfArrayTwo =  new ArrayList<Integer>(Arrays.asList(arrayTwo));
        TreeSet<Integer> setTwo = new TreeSet<Integer>(listOfArrayTwo);
        System.out.println("setTwo is : " + setTwo);

        for (Integer elem1 : arrayOne) {

            boolean exists = setTwo.add(elem1);
            System.out.println("For elem2 [" + elem1 + "], exists [" + exists + "]." );
            if (exists) {
                resultList.add(elem1);
            }
        }

        System.out.println(resultList);

    }

}

【问题讨论】:

  • 数组是否像您的示例一样在开始时排序?
  • 看起来你想要两个数组元素的对称差异。如果这是问题所在,请在此处查看:stackoverflow.com/q/8064570/1065197
  • 对两个数组进行排序并使用 2 个指针(每个数组一个指针)对它们进行迭代是在 O(nlogn) 时间和 O(1) 空间中执行此操作的一种方法。使用 O(n) 空间和 O(n) 时间,您可以创建一个 Map&lt;Integer, Integer&gt; 来计算每个数字的所有出现次数,然后打印计数为 1 的数字。
  • 感谢 Mateusz Dymczyk 的好主意 :)
  • 您好,虽然我的示例看起来已排序,但根据问题陈述应该未排序。这就是为什么我想使用 TreSet 而不是 HashSet。

标签: java arrays algorithm


【解决方案1】:

对数组中的每种类型的项目进行集合。 然后收集那些只有一项的数组变量,因此,独特的项目

【讨论】:

  • Arpan,你能详细说明一下吗?
  • 找到一种方法,通过项目的相似性(或使它们相等的行为)对项目进行分组,并将它们存储在二维数组中。现在,检查生成的二维数组,看看是否有任何块只有一项。如果只有一项,则表示该块中的项是唯一的。
【解决方案2】:

基本上只使用 Collections API(即没有显式迭代)的解决方案是

    Integer[] arrayOne = {1, 2, 3};
    Integer[] arrayTwo = {2, 3, 4};
    Set<Integer> set1 = new HashSet<>(Arrays.asList(arrayOne));
    Set<Integer> set2 = new HashSet<>(Arrays.asList(arrayTwo));
    Set<Integer> uniqueTo1 = new HashSet<>(set1);
    uniqueTo1.removeAll(set2);
    Set<Integer> uniqueTo2 = new HashSet<>(set2);
    uniqueTo2.removeAll(set1);
    Set<Integer> result = new HashSet<>(uniqueTo1);
    result.addAll(uniqueTo2);

    System.out.println(result);

这应该在O(n) 时间运行,除非我遗漏了什么:数组到列表的转换是O(n)Sets 的创建也是如此,remove 是@987654326 上的恒定时间@,所以 removeAll(...)O(n)

【讨论】:

  • 遗憾的是它没有添加来自arrayTwo 的独特元素,所以它没有得到“4”。
  • 感谢詹姆斯的这个想法。但仍在寻找是否可以更优化。
  • 是的,这样做太晚了,但我已修复它,我认为它仍然在 O(n) 中运行。
  • James,我们不能选择 TreeSet 而不是 HashSet 吗?
  • removeTreeSet 的操作是O(log(n)),所以removeAllO(n log(n)),通常会更慢。
猜你喜欢
  • 1970-01-01
  • 2017-07-11
  • 2018-07-05
  • 1970-01-01
  • 1970-01-01
  • 2020-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多