如何在O(N)

时间:2015-09-24 22:37:55

标签: java arrays algorithm performance comparison

我有一个对我来说似乎不可能的问题。我有2个以上的数组,我必须比较常见的值。我应该在O(N)比较中做到这一点,但不能想办法。具体地说是(k-1)N个比较,其中k是数组的数量。我已经缩小了如何采用多个数组并将它们合并为一个数组的范围。我已经知道最小的数组是限制因素所以如果我排序,我可以保存最多的比较。在花了半天时间盯着我的屏幕之后我甚至想出了一种方法来线性地做这个,如果我打折任何重复,但我必须保持重复所以,据我所知,为了比较任何阵列你需要至少2个循环,这将是O(N ^ 2)不是吗?我也不允许散列任何东西。

例如,如果我有{1,3,4,3,4,5}作为主人和{1,1,3,5,9,3,7}和{3,5,8,4, 0,3,2}作为要比较的数组我需要有{3,3,5}的决赛,因为我无法摆脱任何重复。

我不想让任何人编写代码,我只需要知道我应该首先做些什么。

2 个答案:

答案 0 :(得分:0)

如果对列表进行了排序,那么如果您执行以下操作,则相对简单:

List<Integer> intersection = new ArrayList<>();
int i = 0;
int j = 0;
while (i < list1.size() && j < list2.size()) {
  int a = list1.get(i);
  int b = list2.get(j);
  if (a < b) {
    i++;
  } else if (b < a) {
    j++;
  } else { // a == b
    intersection.add(a);
    i++;
    j++;
  }
}

在循环的每次迭代中,数量i + j增加至少1,并且保证循环在i + j >= list1.size() + list2.size()时完成,因此整个事物最多只能执行O(list1.size) ()+ list2.size())比较。

答案 1 :(得分:0)

使用一组int。获取第一个列表,为每个元素设置该索引处的值为1。因此,如果第一个元素是3,则将1放在数组[3]中。现在,我们知道第一个列表中有3个。放1将有助于您区分先前列表中存在的3与当前列表中重复的3。

  1. 遍历所有其他k-1列表
  2. 对于每个元素,检查数组中该索引的值
  3. 如果值为0,请将其设置为此列表编号
  4. 如果该值是小于此列表编号的数字,则此数字是重复的,并且已出现在上一个列表中。
  5. 如果此数字等于此列表索引,则表示此数字已在此列表中出现,但在以前的列表中未出现,因此尚未重复。
  6. 您获得的数字重复,将它们添加到另一个列表中。
  7. 完成所有迭代
  8. 最后打印副本。

    原始错误答案

    1. 创建HashSet<int>
    2. 从master获取所有值并添加到其中 - O(主列表计数)
    3. 现在只需遍历第一个和第二个数组,看看它们的元素是否在HashSet中 - O(每个列表数)