从排序的数组中返回一系列数字的最快方法是什么?

时间:2017-12-08 05:28:30

标签: c++ arrays search find

对于C ++语言,处理运行时(在多核处理器中)的最快方法是什么,从算法设计的角度来看,搜索数组内的数字(例如100到1000之间)(或拼接或更快的速度)用于此目的的数据结构)并返回仅限于10项返回的数字范围?例如golang中的伪代码:

var listofnums := []uint64 
var numcounter := 1
// splice of [1,2,3,4,5,31,32 .. 932536543] this list has 1 billion numeric items.
// the listofnums are already sorted each time an item is added but we do not know the lower_bound or upper_bound of the item list.
// I know I can use binary search to find listofnums[i] where it is smallest at [i] too... I'm asking for suggestions. 
for i:=uint(0); i < len(listofnums); i++ {
    if listofnums[i] > 100 && listofnums[i] < 1000 {
         if listofnums[i]> 1000 || numcounter == 10 {
             return
         }
         fmt.Println("%d",listofnums[i])
         numcounter++
    }
}

这是最快的方法吗?我在C ++中看到了位图结构,但不确定是否可以在这里应用。

我遇到过这个问题,这对于资深程序员来说是完全没问题,但我不知道为什么会被投票。 What is the fastest search method for array?

有人请不要删除这个问题,但让我改一下吗?提前致谢。我希望找到从大量数字项中返回一系列数字的最佳方法。

2 个答案:

答案 0 :(得分:2)

如果我正确理解你的问题,你需要在你的数组中找到两个位置,第一个数字大于或等于100,第二个位置所有数字都小于或等于{ {1}}。

函数std::lower_boundstd::upper_bound执行二元搜索,旨在找到这样的范围。

对于数组,在1000中我们通常使用std::vector并使用一对迭代器表示范围的开头和结尾。

所以这样的事情可能就是你所需要的:

C++

你可以像这样迭代这个范围:

std::pair<std::vector<int>::iterator, std::vector<int>::iterator>
    find_range(std::vector<int>& v, int min, int max)
{
    auto begin = std::lower_bound(std::begin(v), std::end(v), min);

    // start searching after the previously found value
    auto end = std::upper_bound(begin, std::end(v), max);

    return {begin, end};
}

您可以从范围(慢)创建一个新的向量,如下所示:

auto range = find_range(v, 100, 1000);

for(auto i = range.first; i != range.second; ++i)
    std::cout << *i << '\n';

答案 1 :(得分:1)

我的第一次尝试。

特点:

  • logN时间复杂度

  • 创建一个数组切片,不复制数据

  • 第二次二进制搜索在第一次

  • 的基础上最小化搜索空间

可能的改进:

  • 如果n很小,第二次二分搜索将是一种悲观。最好只计算n次。

#include <vector>
#include <cstdint>
#include <algorithm>
#include <iterator>
#include <iostream>

template <class Iter> struct range
{
    range(Iter first, std::size_t size) : begin_(first), end_(first + size) {}

    auto begin() const { return begin_; }
    auto end() const { return end_; }

    Iter begin_, end_;
};

template<class Iter> range(Iter, std::size_t) -> range<Iter>;

auto find_first_n_between(std::vector<std::int64_t>& vec, 
                          std::size_t n, 
                          std::int64_t from, std::int64_t to)
{
    auto lower = std::lower_bound(begin(vec), end(vec), from);
    auto upper = std::upper_bound(lower, end(vec), to);
    auto size = std::min(n, std::size_t(std::distance(lower, upper)));
    return range(lower, size);
}


int main()
{
    std::vector<std::int64_t> vec { 1,2,3,4,5,6,7,8,15,17,18,19,20 };
    auto slice = find_first_n_between(vec, 5, 6, 15);

    std::copy(std::begin(slice), std::end(slice), std::ostream_iterator<std::int64_t>(std::cout, ", "));
}