在无序数组中搜索元素的最快方法



我今天偶然发现了这个问题,并试图找到一个比0 (N)更好的解决方案,但无法想出一个。

搜索了SO,但没有找到这个问题。

有比O(n)更好的解决方案吗?还是这个问题没有比O(n)更好的解决方案?

我最初的想法是二分搜索,但你需要对它进行排序,这又是>n。我还想过对搜索元素可能所属的数组的一半应用快速排序,但我们最初进行n次比较,然后才丢弃另一半。我是做对了还是看错了方向?

我在c++中尝试解决方案,没有javascript的IndexOf()或c# Array.find()或LINQ的。

让它平行。将数组分成块并并行搜索。复杂度将是0 (n),但运行时间将少得多。实际上它和no成正比。

你可以在c++中使用并行模式库

你是对的,最快的方法是简单地遍历数组并查找它。没有进一步的信息,你没有更好的办法。

除非你有一台量子计算机。

如果您只搜索一个元素一次,只需遍历它。没有比这更快的方法了。

如果您搜索多次,那么为它建立索引(或者排序,如果您愿意)并使以下搜索快速(log(n))是值得的。

通常,我们在一次迭代中检查数组的一个元素…它需要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,并计算两个循环对相同数组大小的不同测试用例所花费的时间…这些就是结果!

每次迭代一个元素

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

每次迭代5个元素

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

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

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

如果您不进行并行搜索,那么您可以将键插入到数组的末尾作为哨兵值,并且只进行'n'比较而不是进行2n比较。

详情请参考以下问题:使用哨兵线性搜索的意义是什么?

您可以使用这种方法搜索0(1)的元素。

创建一个MAP。当你插入一个值,然后为键赋值为'1',并再次搜索它只是检查数组是否存在。

下面是代码:-

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    map<int,int> map;
    for(int i=0;i<n;i++){
        int k;
        cin>>k;
        map[k]=1;
    }
    int num;
    cin>>num;
    if(map[num]){
        cout<<"FOUND"<<endl;
    }else{
        cout<<"NOT FOUND"<<endl;
    }
    return 0;
}

Input: 
5    // *no. of elements*
6 4 7 3 2  //*elements* 
3    // *number to find*

输出:FOUND

这可以通过使用一些技巧来解决。在无序数组中,如果我们遍历它,在最坏情况下(当元素出现在最后一个索引时)的复杂度将是O(N),其中N是数组的大小。这就是诀窍。首先检查最后一个索引,这样如果元素出现在最后一个索引(最坏的情况),我们的代码将在0(1)内执行。然后是遍历并找到元素的代码。所以,现在最坏情况下的复杂度是0 (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;
}

在寻找比线性搜索更快的方法时,我偶然发现了"前后"线性搜索方法(https://medium.com/@insomniocode/search-algorithm-front-and-back- unsort-86d7a4bfc258),我在几个实例上测试了它,结果证明它确实更快,但不是很明显。在我看来值得一试!

然而,还有另一种逻辑…

(偶数存储在偶数地址中)

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

  • 如果搜索元素为"偶数",则只搜索偶数

  • 可以通过以下逻辑跳过搜索中的一半元素

例如:

  • 如果有100个元素以无序方式存储并搜索元素是98....因为搜索号是偶数…你可以跳过全部为奇数地址(因此跳过50个元素),现在搜索完成仅限其余50个偶数地址....

您可以将元素划分并并行搜索或使用"pivot key"排序到剩余的50个元素或任何其他搜索方法

在快速排序过程中使用分区方法的算法效率如何?

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

  2. 将整个列表划分为2部分。

  3. 重复步骤2、3,直到确定元素是否存在。

我不确定以上算法的复杂度,但看起来肯定比快速排序算法的复杂度要小:(n log n).

给定下面的数组,你可以做并行搜索。

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;
                }
              }
            }
          }
        }
      }
    }
  }
}

有可能使你的程序运行得比O(n)快。

首先使用归并排序算法对数组进行排序,然后使用二分查找来查找元素。两种算法的运行时间都是O(log_2(n))。把这两个复杂度加在一起,你得到2*log_2(n),也就是O(log_2(n))和见证物C = 2

相关内容

最新更新