Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 求数组中任意一对相等元素之间的最小距离_C++_Arrays_Algorithm_Vector - Fatal编程技术网

C++ 求数组中任意一对相等元素之间的最小距离

C++ 求数组中任意一对相等元素之间的最小距离,c++,arrays,algorithm,vector,C++,Arrays,Algorithm,Vector,给定一些整数数组A=[a0,a1,…,an],求出ai和aj之间的最小距离,使ai=aj和i!=j(或表明不存在此类指数) 我在C++中实现了一个天真的O(n2)方法,包括迭代数组,寻找相等的元素,并适当地更新最小距离: #include <vector> #include <climits> #include <algorithm> int MinPair(const std::vector<int>& nums) { int

给定一些整数数组A=[a0,a1,…,an],求出ai和aj之间的最小距离,使ai=aj和i!=j(或表明不存在此类指数)

我在C++中实现了一个天真的O(n2)方法,包括迭代数组,寻找相等的元素,并适当地更新最小距离:

#include <vector>
#include <climits>
#include <algorithm>

int MinPair(const std::vector<int>& nums)
{
    int ret = std::numeric_limits<int>::max();
    for(int i = 0; i != nums.size(); ++i)
    { 
        for(int j = 0; j != i; ++j)
        { 
            if(nums[i] == nums[j])  
                ret = std::min(ret, i - j);
        }
    }

    if(ret == std::numeric_limits<int>::max()) 
        return -1;

    return ret;
}
#包括
#包括
#包括
int MinPair(const std::vector和nums)
{
int ret=std::numeric_limits::max();
对于(int i=0;i!=nums.size();++i)
{ 
对于(int j=0;j!=i;++j)
{ 
if(nums[i]==nums[j])
ret=std::min(ret,i-j);
}
}
如果(ret==std::numeric_limits::max())
返回-1;
返回ret;
}
这工作得很好,但有人告诉我,有一个更“高效”的实现涉及std::map,而没有对什么更高效进行太多的澄清。也就是说,可以遍历输入数组并在映射中存储元素的第一个匹配项,然后为每个后续匹配项查找该匹配项与映射中该元素的第一个索引之间的距离。如果该距离小于当前最小值,则更新该最小值


但是,我看不出哪种方式更“有效”。就时间复杂度而言,您仍然需要遍历输入数组(O(n)),并且使用std::map::find来确定元素是否是第一次出现也是O(n),总复杂度为O(n2)。就空间复杂度而言,除了数组/向量之外,还必须存储贴图。我到底错过了什么


编辑:我错误地假设map::find是O(n);插入和查找操作实际上是O(logn),即使假设使用二进制搜索之类的基本实现,也可以立即看到它。

您可以将每个元素映射到它的一组索引。因此,您将有一个类似于
的映射m
,并遍历向量:
for(inti=0,i
。之后,您可以遍历映射,如果元素有多个索引,则可以找到索引之间的最小距离。应该是O(nlog(n))。

我最初发布了一个与grigor提到的解决方案类似的编码解决方案。然后我意识到有一个明显的优化,使整个事情在O(N)时间内为最佳情况和平均情况工作

typedef pair<bool, int> LastPositionFound;

int MinPair(const std::vector<int>& nums)
{
    unordered_map<int, LastPositionFound> table; // maps value found in array to the last position that value was seen at.
    int best_distance = -1;

    for (size_t index = 0; index < nums.size(); index++)
    {
        int value = nums[index];
        LastPositionFound& lpf = table[value];  // returns {false,0} if not found
        if (lpf.first)
        {
            int distance = index - lpf.second;
            if ((distance < best_distance) || (best_distance == -1))
            {
                best_distance = distance;
            }
        }

        // update reference to hash table entry
        lpf.first = true;
        lpf.second = index;
    }
    return best_distance;
}
typedef对LastPositionFound;
int MinPair(const std::vector和nums)
{
无序的_map table;//将在数组中找到的值映射到上次看到该值的位置。
int最佳距离=-1;
对于(size_t index=0;index
“使用std::map::find来识别元素是否是第一次出现也是O(n)”您确定吗?文档说明:“复杂性:大小为对数。”保持数组排序,您可以在O(n)时间内搜索重复的数组。在搜索之前,您的容器是已排序还是未排序?@arekolek您是对的,它确实是对数的!保留所有的价值观有什么意义?将重复元素的索引与以前发生的索引进行比较就足够了。为什么
O(n log n)
?地图和集合都有用于插入< <代码> o(1)< /> >的平均运行时间。C++中的保罗(有序)集和映射具有O(log n)操作。C还具有期望的O(1)复杂度的无序映射。@保罗问题是标记C++和回答提到的代码>地图和 SET/COD>,这是C++ C++标准API中有序容器类的名称,其中O(log n)操作复杂。