简体   繁体   中英

What is the fastest way to return a range of numbers from a sorted array of numbers?

For C++ language, what's the fastest way in processing run-time (in multi core processors), from an algorithm design viewpoint, to search numbers (eg between 100 and 1000) that are within an array (or splice or whatever faster data structures for the purpose of this) and return the range of numbers limited to only 10 items returned? eg pseudocode in 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++
    }
}

is this the fastest way? I saw bitmap structures in C++ but not sure if can be applied here.

I've come across this question, which is perfectly fine for veteran programmers to ask but I have no idea why it's down voted. What is the fastest search method for array?

Can someone please not remove this question but let me rephrase it? Thanks in advance. I hope to find the most optimum way to return a range of numbers from a large array of numeric items.

If I understand your problem correctly you need to find two positions in your array, the first of which all numbers are greater than or equal to 100 and the second of which all numbers are less than or equal to 1000 .

The functions std::lower_bound and std::upper_bound do binary searches designed to find such a range.

For arrays, in C++ we usually use a std::vector and denote the beginning and end of ranges using a pair of iterators .

So something like this may be what you need:

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

You can iterate over that range like this:

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

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

You can create a new vector from the range (slow) like this:

std::vector<int> selection{range.first, range.second};

My first attempt.

Features:

  • logN time complexity

  • creates an array slice, no copying of data

  • second binary search minimises the search space on the basis of the first

possible improvements:

  • if n is small, the second binary search would be a pessimisation. Better to simply count forward up to n times.

#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, ", "));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM