c++中使用哪个STL来查找0(1)中的值索引

Which STL to use to find index by value in O(1) in C++

本文关键字:索引 c++ STL 查找      更新时间:2023-10-16

假设我有一个数组arr[] = {1 , 3 , 5, 12124, 24354, 12324, 5}

我想知道O(1)中值5(即2)的索引。
我该怎么做呢?

p。S:
1. 在整个程序中,我将只查找索引,反之亦然(通过索引获取值)。
2.

如果您可以保证数组中没有重复项,那么您最好的选择可能是创建一个unordered_map,其中映射键是数组值,映射值是它的索引。

我在下面写了一个将数组转换为unordered_map的方法。

#include <unordered_map>
#include <iostream>
template <typename T>
void arrayToMap(const T arr[], size_t arrSize, std::unordered_map<T, int>& map)
{
    for(int i = 0; i < arrSize; ++i) {
        map[arr[i]] = i;
    }
}
int main()
{
    int arr[] = { 1 , 3 , 5, 12124, 24354, 12324, 5 };
    std::unordered_map<int, int> map;
    arrayToMap(arr, sizeof(arr)/sizeof(*arr), map);
    std::cout << "Value" << 't' << "Index" << std::endl;
    for(auto it = map.begin(), e = map.end(); it != e; ++it) {
        std::cout << it->first << "t" << it->second << std::endl;
    }
}

但是,在您的示例中,您使用了两次值5。这会导致上面代码中的奇怪输出。输出的映射没有索引为2的值。即使使用数组,也会遇到类似的问题(即应该使用2还是6?)。

如果确实需要两个值,可以使用unordered_multimap,但是访问元素的语法不像使用operator[]那么简单(必须使用返回迭代器的unordered_multipmap::find())。

template <typename T>
void arrayToMap(const T arr[], size_t arrSize, std::unordered_multimap<T, int>& map)
{
    for(int i = 0; i < arrSize; ++i) {
        map.emplace(arr[i], i);
    }
}

最后,您应该考虑到unordered_map的快速查找时间O(1)带来了一些开销,因此它比简单数组使用更多的内存。但是,如果您最终使用数组(相对而言内存效率更高),则可以保证搜索特定值的时间为O(n),其中n是该值的索引。


编辑-如果您需要保留索引最低的副本而不是索引最高的副本,您只需颠倒插入顺序:

template <typename T>
void arrayToMap(const T arr[], size_t arrSize, std::unordered_map<T, int>& map)
{
    for(int i = arraySize - 1; i >= 0; --i) {
        map[arr[i]] = i;
    }
}

使用c++ 11中的std::unordered_map将元素映射为键,索引映射为值。然后您可以在 amortized O(1) 复杂度中得到查询的答案。std::unordered_map可以工作,因为没有你说的重复,但会花费你线性大小的额外空间。

如果你的值的范围不是太大,你也可以使用数组。这会产生更好的theta(1)复杂度。

使用unordered_multimap(仅限c++ 11)将值作为键,并将位置索引作为值