数组列表算法 - 访谈

时间:2012-04-26 14:07:38

标签: java algorithm collections

我今天在接受采访时被问到这个问题。我尝试过一个解决方案,但想知道是否有更好的解决方法:

问题:我有一个arraylist说500,000个元素,使得arraylist的每个元素的值与索引相同。例如:list.get(0)= 0; list.get(1)= 1 ...等。但是只有一个元素与这个排序不同步[即list.get(i)!= i]。你怎么找到那个元素。

我的答案:使用多个线程迭代列表,每个线程在每次比较list.get(i)和i时处理arraylist的某个拼接。找到元素后,设置一些布尔变量以指示其他线程已找到该元素。

有没有办法解决这个问题而不迭代列表?还是更好的方式?

6 个答案:

答案 0 :(得分:12)

在最糟糕的情况下,您必须检查每个元素,因此无法改善O(n)时间复杂度。

考虑到这一点,最好的算法是从头到尾扫描阵列列表。这样就可以充分利用可用的内存带宽。

我并不完全清楚线程是如何或为何进入图片的。这似乎不合时宜。这是问题的一部分吗?

答案 1 :(得分:4)

答案是:一次迭代。你提到原因的并发性是他们正在捕捉的东西。

实际上从java 8开始,解决方案是否并行很简单。我认为最多会带来:

OptionalInt foundInt = IntStream.range(0, list.size())
    .parallelStream()
    .filter(i -> i != list.get(i))
    .findAny();

答案 2 :(得分:2)

你不能比O(n)做得更好。

其次,我认为在这些问题中谈论线程和多线程是一个坏主意。它们根本不感兴趣。最后,你有一个O(无论如何)的运行时,你的常量被移除了。

也许面试官意味着一个排序数组,其元素从0到n-1,索引0到n-1。然后将一个元素移动到不同的位置。但这意味着所有剩余的元素都有不同的索引!在这种情况下,您可以使用二分查找改进搜索:

然后你可以在O(log n)中获取元素。从中间开始,检查索引是否等于元素。如果相等,则对半部的上半部分进行相同的处理,如果不使用另一部分的话。

答案 3 :(得分:0)

继续@ aix的回答,如何对每个循环进行2次检查:

for (int i = 0; i < list.size / 2; i++)
{
  if (i != list.get(i))
  {
    return i;
  }
  else if (list.size - i != list.get(list.size - i)
  {
    return list.size - i;
  }
}

答案 4 :(得分:0)

1. iterate through the list 
2. check for the condition in the elements
3. when that only element found break out the loop... 

我不认为Thread进入竞技场......

答案 5 :(得分:0)

ArrayList<Integer> s = new ArrayList<Integer>();

for (int i=0; i<500000; i++) {
    s.add(i);
}

s.set(13, 500002);

for (int j=0; j<s.size(); j++) {
    if (j != s.get(j)) {
        System.out.println(j + " " + s.get(j));
    }   
}