Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/11.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++ CodeSignal:使用c+;超出了执行时间限制+;_C++_Execution Time - Fatal编程技术网

C++ CodeSignal:使用c+;超出了执行时间限制+;

C++ CodeSignal:使用c+;超出了执行时间限制+;,c++,execution-time,C++,Execution Time,我正试图解决编程问题,首先复制代码信号。问题是“给定一个数组a,该数组只包含1到a.length范围内的数字,找到第二次出现的索引最小的第一个重复数字” 例如:对于a=[2,1,3,5,3,2]输出应该是firstDuplicate(a)=3 有两个重复:数字2和3。第二次出现的3的索引比第二次出现的2的索引小,因此答案是3 使用这段代码,我通过了21/23测试,但它告诉我程序超过了测试22的执行时间限制。我该如何让它更快地通过剩下的两项测试 #include <algorithm>

我正试图解决编程问题,首先复制代码信号。问题是“给定一个数组
a
,该数组只包含
1
a.length
范围内的数字,找到第二次出现的索引最小的第一个重复数字”

例如:对于
a=[2,1,3,5,3,2]
输出应该是
firstDuplicate(a)=3

有两个重复:数字2和3。第二次出现的3的索引比第二次出现的2的索引小,因此答案是3

使用这段代码,我通过了21/23测试,但它告诉我程序超过了测试22的执行时间限制。我该如何让它更快地通过剩下的两项测试

#include <algorithm>

int firstDuplicate(vector<int> a) {
    vector<int> seen;
    
    for (size_t i = 0; i < a.size(); ++i){
        if (std::find(seen.begin(), seen.end(), a[i]) != seen.end()){
            return a[i];
        }else{
            seen.push_back(a[i]);
        }
    }
    
    if (seen == a){
        return -1;
    }
    
}

#包括
int firstDuplicate(向量a){
可见向量;
对于(大小i=0;i
std::find
是容器中第一个和最后一个元素(或直到找到数字)之间距离的线性时间复杂度,因此最坏情况复杂度为O(N),因此您的算法为O(N^2)

Yyu不应该将数字存储在向量中并每次搜索它,而应该使用
std::map
进行哈希运算,以存储遇到的数字,并在迭代时返回一个数字,如果该数字已经存在于映射中

std::map<int, int> hash;
for(const auto &i: a) {
    if(hash[i])
        return i;
    else
        hash[i] = 1;
}
std::map散列;
用于(常数自动和i:a){
if(散列[i])
返回i;
其他的
散列[i]=1;
}

编辑:
std::unordered\u map
如果键的顺序无关紧要,则效率更高,因为插入时间复杂度在平均情况下与
std::map

的对数插入复杂度相比是恒定的,无论何时当您被问及“查找重复项”、“查找缺少的元素”或“找到应该存在的东西”,你的第一本能应该是“强”。使用哈希表< /强>。在C++中,有<代码>未排序的地图> /代码>和<代码>无序的集合> /COD>类,用于此类编码练习。<代码>无序的集合> /代码>实际上是一个布尔的键的映射。< /P> 另外,通过引用而不是值传递向量。通过值传递会导致复制整个向量的开销

此外,这种比较最终似乎代价高昂,也没有必要

这可能更接近您想要的:

#include <unordered_set>


int firstDuplicate(const vector<int>& a) {
    std::unordered_set<int> seen;
    
    for (int i : a) {
       auto result_pair = seen.insert(i);
       bool duplicate = (result_pair.second == false);
       if (duplicate) {
          return (i);
       }
    }

    return -1;
   
}
#包括
int firstDuplicate(常量向量&a){
std::看到无序的_集;
对于(int i:a){
自动结果\u pair=seen.insert(i);
bool duplicate=(result_pair.second==false);
如果(重复){
回报(i);
}
}
返回-1;
}

这可能是一个不必要的优化,但我认为我应该尝试更好地利用该规范。哈希表主要用于从可能的键到实际键的转换非常稀疏的情况,也就是说,只使用了一小部分可能的键。例如,如果您的键是str长度最长可达20个字符,理论上最大键数为25620。有这么多可能的键,很明显,任何实用程序都不会存储超过一个极小的百分比,因此哈希表是有意义的

然而,在本例中,我们被告知输入是:“一个数组a,它只包含1到a.length范围内的数字”。因此,即使有一半的数字是重复的,我们也使用了50%的可能键

在这种情况下,我会使用
std::vector
,而不是哈希表(尽管它经常被恶意攻击),并期望在绝大多数情况下获得更好的性能

intfirstduplicate(std::vector const&input){
std::vector seen(input.size()+1);
对于(自动i:input){
如果(见[i])
返回i;
见[我]=真;
}
返回-1;
}
这里的优势相当简单:至少在典型情况下,
std::vector
使用专门化来存储
bool
s,每个位只存储一个位。这样,我们每个输入数只存储一个位,这增加了存储密度,因此我们可以期待缓存的出色使用。特别是,只要缓存中的字节数至少比输入数组中元素数的1/8多一点,我们可以预期看到的所有
大部分时间都在缓存中

现在不要搞错了:如果你环顾四周,你会发现相当多的文章指出
vector
有问题——在某些情况下,这是完全正确的。有一些地方和时间应该避免
vector
。但它的限制并不适用于我们在这里使用它的方式——而且它确实给我们的应用带来了优势存储密度非常有用,特别是对于这种情况


我们也可以编写一些自定义代码来实现位图,这样会比
vector
提供更快的代码。但是使用
vector
很容易,而且编写我们自己的更高效的替换代码是相当多的额外工作…

使用hashmap而不是vectorRead读取编译器的良好文档(例如…)和调试程序(例如)。参见.Upand和.C.。从现有的开源C++软件中得到启发,例如,考虑使用一些<代码> STD::unOrdEdEdMult//Cord>比 STD::MAP< /COD>(哈希表与树插入)更有效.
std::unordered_set
完成了与布尔值映射相同的事情。是的,您是对的,与
std::map
的log(n)相比,插入时间在平均情况下是恒定的。