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)相比,插入时间在平均情况下是恒定的。