搜索未排序数组中元素的最快方法

时间:2011-10-05 04:45:36

标签: algorithm visual-c++

我今天刚刚提出这个问题,并且正在尝试一种比O(N)更好的解决方案,但却找不到一个。

通过SO搜索但未找到此问题。

有没有比O(n)更好的解决方案,还是一个无法解决的问题?

我最初的想法是二进制搜索,但是你需要再次对它进行排序> n。我还考虑过将quicksort应用于搜索元素可能属于的数组的一半,但我们再次进行n次比较,之后才丢弃另一半。我是正确的,还是我在错误的方向上看待解决方案?

我正在尝试使用c ++解决方案而没有javascript的IndexOf()或C#Array.find()或LINQ。

12 个答案:

答案 0 :(得分:11)

让它平行。将数组划分为块并并行搜索。 复杂性将是O(n),但运行时间会少得多。实际上它与否成正比。您拥有的处理器。

您可以在C ++中使用Parallel Patterns Library

答案 1 :(得分:5)

你是对的,最快的方法是简单地遍历数组并寻找它。没有进一步的信息,你无能为力。

除非你有quantum computer,否则就是。

答案 2 :(得分:4)

如果您正在搜索一个元素,只需迭代它。没有办法让它更快。

如果您正在多次搜索,那么将其编入索引(或者对其进行排序,如果您愿意)是值得的,并快速进行以下搜索(log(n))。

答案 3 :(得分:1)

如果没有排序,则必须检查每个元素。

答案 4 :(得分:1)

您可以使用此方法使用O(1)搜索元素。

只需创建一个 MAP 即可。当您刚插入一个值时,为此键将值分配为'1',然后再次搜索它,只需检查该数组是否存在。

下面是代码:-

set

输出:找到

答案 5 :(得分:0)

但是,还有另一种逻辑……

(偶数地址中存储了数字)

  • 首先检查搜索元素是奇数还是偶数

  • 如果搜索元素为“偶数”,则仅搜索偶数 地址(创建循环增量以跳过奇数地址)

  • 通过该逻辑可以将元素从搜索中跳过

例如:

  • 如果有100个元素以无序方式存储并搜索 元素是98 ....由于搜索数是偶数... u可以跳过 所有奇数地址(因此跳过了50个元素)现在完成搜索 仅剩下50个地址。...

您可以划分元素并并行搜索,或者使用“枢轴键”排序以保留50个元素或其他任何搜索方法

答案 6 :(得分:0)

在快速排序过程中采用如下划分方法的算法的效率如何?

  1. 在列表中随机选择一些值(我们称之为v)。

  2. 将整个列表分为两部分。左部分包含所有小于v的元素。右部分包含所有大于v的元素。

  3. 重复步骤2、3,直到您确定该元素存在或不存在。

我不确定上述算法的复杂性,但看起来绝对比快速排序算法的复杂性小:(n log n)。

答案 7 :(得分:0)

如果不进行并行搜索,则可以将键插入到数组末尾作为标记值,​​并仅使用“ n”个比较而不是2n个比较进行搜索。

有关更多详细信息,请参考以下问题: What's the point of using linear search with sentinel?

答案 8 :(得分:0)

这可以通过一些技巧来解决。同样地,如果我们遍历未排序的数组,则在最坏情况下(当元素位于最后一个索引处时)的复杂度将为O(N),其中N是数组的大小。因此,这就是窍门。首先检查最后一个索引,以便如果元素位于最后一个索引(最坏的情况),我们的代码将在O(1)中执行。之后,遍历代码并查找元素。因此,现在最糟糕的情况是O(N-1)。

int findElement(int N, int arr[], int element){
  if(arr[N]==element){
    return i;
  }
  for(int i=0; i<N-1; i++){
    if(arr[i]==element)
      return i;
  }
  return -1;
}

答案 9 :(得分:0)

通常,我们在一次迭代中检查数组的一个元素……这需要 n 次迭代才能完全循环遍历数组…… 因此,最坏情况的时间复杂度变为 O(n)。

for(int i=0;i<s;i++){   // s = array size
    if(arr[i] == n)     // n = element to be searched
        return i;
}

但我的实验是在一次迭代中检查多个元素。 假设每次迭代有 5 个元素。因此,在这种情况下,for 循环将如下所示:

// s = array size
// n = element to be searched
for(int i=0;i<s;i+=5){  // notice the increment in i here...
    if(arr[i] == n)   
        return i;
    
/* check the next four indexes as well as if arr[i] is the last element of the array */ 
    else if( arr[i+1] == n && i+1 < s)
        return i+1;
    else if(arr[i+2] == n && i+2 < s)
        return i+2;
    else if(arr[i+3] == n && i+3 < s)
        return i+3;
    else if(arr[i+4] == n && i+4 < s)
        return i+4;
}

这里,理论上时间复杂度应该变成 O(n/5)...

但是,当我通过获取大小为 1000000 且元素 1 到 1000000 随机排列的数组来执行程序并计算两个循环对相同数组大小的不同测试用例所花费的时间时......这些就是结果!< /p>

每次迭代一个元素

  1. 时间复杂度(以微秒为单位):4105 4180 4108 4115 4087 4137 4094 4089 4141 4167 4082 4084 4114 4118 4099

每次迭代 5 个元素

  1. 时间复杂度(以微秒为单位):1318 1382 1384 1297 1364 1289 1351 1617 1300 1289 1395 1385 1349 1329 1369

所以,正如我所看到的,时间复杂度发生了重大变化!

答案 10 :(得分:-2)

给定以下数组,您可以进行并行搜索。

const array = [1, 2, 3, 4, 5, 6, 7, 3];
const search = 3;

for (let i = 0; i < array.length; i++) {
  if (array[i] === search) {
    console.log(i);
    break;
  }
  if (typeof array[i + 1] !== "undefined") {
    if (array[i + 1] === search) {
      console.log(i + 1);
      break;
    }
    if (typeof array[i + 2] !== "undefined") {
      if (array[i + 2] === search) {
        console.log(i + 2);
        break;
      }
      if (typeof array[i + 3] !== "undefined") {
        if (array[i + 3] === search) {
          console.log(i + 3);
          break;
        }
        if (typeof array[i + 4] !== "undefined") {
          if (array[i + 4] === search) {
            console.log(i + 4);
            break;
          }
          if (typeof array[i + 5] !== "undefined") {
            if (array[i + 5] === search) {
              console.log(i + 5);
              break;
            }
            if (typeof array[i + 6] !== "undefined") {
              if (array[i + 6] === search) {
                console.log(i + 6);
                break;
              }
              if (typeof array[i + 7] !== "undefined") {
                if (array[i + 7] === search) {
                  console.log(i + 7);
                  break;
                }
              }
            }
          }
        }
      }
    }
  }
}

答案 11 :(得分:-5)

可以使您的程序运行速度比O(n)快。

首先使用合并排序算法对数组进行排序,然后使用二进制搜索来查找元素。两种算法的运行时间均为O(log_2(n))。将这两个复杂度加在一起,您得到2*log_2(n),它与见证人O(log_2(n))C = 2