查找向量中缺少的第一个元素 这个问题,但我找不到C++。< /P>
如果我有一个向量和一个起始数字,std::algorithm是否为我提供了一种查找下一个最高缺失数字的方法 很明显,我可以用嵌套的循环来写这篇文章,我无法摆脱我正在重新发明轮子的感觉 例如,给定:查找向量中缺少的第一个元素 这个问题,但我找不到C++。< /P>,c++,algorithm,vector,counting,missing-data,C++,Algorithm,Vector,Counting,Missing Data,如果我有一个向量和一个起始数字,std::algorithm是否为我提供了一种查找下一个最高缺失数字的方法 很明显,我可以用嵌套的循环来写这篇文章,我无法摆脱我正在重新发明轮子的感觉 例如,给定:向量foo{13,8,3,6,10,1,7,0} 起始编号0应为2 起始编号6应为9 起始编号-2应为-1 编辑: 到目前为止,所有的解决方案都需要排序。实际上,这可能是必需的,但必须创建一个临时排序的向量来适应这一点,因为foo必须保持不变。第一种解决方案: 对向量进行排序。找到起始号码,看看下一个号
向量foo{13,8,3,6,10,1,7,0}代码>
起始编号0
应为2
起始编号6
应为9
起始编号-2
应为-1
编辑:
到目前为止,所有的解决方案都需要排序。实际上,这可能是必需的,但必须创建一个临时排序的向量来适应这一点,因为foo
必须保持不变。第一种解决方案:
对向量进行排序。找到起始号码,看看下一个号码是什么。
这将取O(NlogN),其中N是向量的大小
第二种解决方案:
如果数字范围很小,例如(0,M),则可以创建大小为M的布尔向量。对于每个初始向量数,使该索引的布尔值为真。稍后,通过检查布尔向量,您可以看到下一个缺失的数字。这将需要O(N)时间和O(M)辅助存储器。
- 首先需要对向量进行排序。用这个
- 查找与给定元素大于或等于的第一个元素。(元素必须至少部分有序)
- 从那里,您可以在拥有连续元素的同时进行迭代
<重复>处理重复:一种方法是:我在迭代时考虑连续的和相等的元素。另一种方法是添加一个先决条件,即向量/范围包含唯一的元素。我选择前者是因为它可以避免删除元素
以下是如何从已排序向量中消除重复项:
v.erase(std::unique(v.begin(), v.end()), v.end());
我的实施:
// finds the first missing element in the vector v
// prerequisite: v must be sorted
auto firstMissing(std::vector<int> const &v, int elem) -> int {
auto low = std::lower_bound(std::begin(v), std::end(v), elem);
if (low == std::end(v) || *low != elem) {
return elem;
}
while (low + 1 != std::end(v) &&
(*low == *(low + 1) || *low + 1 == *(low + 1))) {
++low;
}
return *low + 1;
}
关于排序的说明:从OP的评论中,他正在寻找一种不会修改向量的解决方案
您必须对向量进行排序,以获得有效的解决方案。如果修改向量不是一个选项,您可以创建一个副本并处理它
如果您执意不进行排序,那么有一种蛮力解决方案(非常低效-O(n^2)):
至少就我所知,没有一种标准的算法可以直接实现你所要求的
如果您想用O(nlogn)这样的复杂度来完成它,您可以从对输入进行排序开始。然后使用std::upper_bound
查找您请求的号码(如果存在)的(最后一个实例)。从那里,你会发现一个数字与前一个数字相差不止一个。从那里,您可以扫描集合中连续数字之间大于1的差值
在实际代码中执行此操作的一种方法如下:
#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
#include <iterator>
int find_missing(std::vector<int> x, int number) {
std::sort(x.begin(), x.end());
auto pos = std::upper_bound(x.begin(), x.end(), number);
if (*pos - number > 1)
return number + 1;
else {
std::vector<int> diffs;
std::adjacent_difference(pos, x.end(), std::back_inserter(diffs));
auto pos2 = std::find_if(diffs.begin() + 1, diffs.end(), [](int x) { return x > 1; });
return *(pos + (pos2 - diffs.begin() - 1)) + 1;
}
}
int main() {
std::vector<int> x{ 13, 8, 3, 6, 10, 1,7, 0};
std::cout << find_missing(x, 0) << "\n";
std::cout << find_missing(x, 6) << "\n";
}
#包括
#包括
#包括
#包括
#包括
int find_缺失(std::vector x,int number){
std::sort(x.begin(),x.end());
auto pos=std::上限(x.begin(),x.end(),number);
如果(*位置-编号>1)
返回号码+1;
否则{
std::向量差异;
标准::相邻插入器差异(位置,x.end(),标准::后插入器(差异));
auto pos2=std::find_if(diffs.begin()+1,diffs.end(),[](int x){return x>1;});
返回*(pos+(pos2-diff.begin()-1))+1;
}
}
int main(){
std::向量x{13,8,3,6,10,1,7,0};
std::cout所以我想我应该发布一个答案。我不知道std::算法中有什么可以直接实现这一点,但是结合向量
可以在O(2N)中实现
模板
T发现_缺失(常量向量&v,T元素){
向量范围(v.size());
elem++;
对于每个(v.begin()、v.end()、[&](const T&i){if((i>=elem&&i-elem
我认为OP是在寻找更具体的惯用C++-ish,而不是可以使用的基本算法的一般描述。(但是,+1.即使可能,也不是所有东西都能从STL化中受益。)顺便说一下,通过忽略[x+1,x+N]范围之外的值,可以调整第二种方法,使其在M不小的情况下也能工作。是的,辅助内存将是O(N)而不是O(M)@但我的问题是我不能对向量进行排序,否则我只需要维护一个已排序的向量并执行此操作:我当前的解决方案是维护一个向量
。这可能会很好:(在我看来,上限
在这里比下限
更有意义。如果请求的数字有多个实例,你会想要最后一个,而不是第一个。@JerryCoffin我考虑过这一点,但是使用上限你无法判断你的元素是否在范围内。如果不是,那么元素就是第一个丢失的。看起来类似于if(*result==input\u number)
是一种非常简单的方法,可以确定返回的迭代器是否引用了较高数字的输入数字。还要注意,如果数字不存在,下限
和上限
都将返回完全相同的结果(一个迭代器,用于下一个比请求的项更大的项)。@JerryCoffin是的。但是如果容器中有重复项,alg将失败得很惨,无论上界的下界是什么。(将发现第一个重复项作为第一个丢失的项)将进行编辑。@bolov感谢您的解决方案!从所有的答案来看,似乎处理此问题的唯一方法是对向量进行排序,这让我很难过,但事实就是如此。std::upper_bound
很有趣。但我认为比较函数不能调整到足以使其在未排序的容器上工作。我真正喜欢的是什么如果没有这样的话,它是可以工作的
int main() {
auto v = std::vector<int>{13, 8, 3, 6, 10, 1, 7, 7, 7, 0};
std::sort(v.begin(), v.end());
for (auto n : {-2, 0, 5, 6, 20}) {
cout << n << ": " << firstMissing(v, n) << endl;
}
return 0;
}
-2: -2
0: 2
5: 5
6: 9
20: 20
auto max = std::max_element(std::begin(v), std::end(v));
if (elem > *max) {
return elem;
}
auto i = elem;
while (std::find(std::begin(v), std::end(v), i) != std::end(v)) {
++i;
}
return i;
#include <iostream>
#include <algorithm>
#include <vector>
#include <numeric>
#include <iterator>
int find_missing(std::vector<int> x, int number) {
std::sort(x.begin(), x.end());
auto pos = std::upper_bound(x.begin(), x.end(), number);
if (*pos - number > 1)
return number + 1;
else {
std::vector<int> diffs;
std::adjacent_difference(pos, x.end(), std::back_inserter(diffs));
auto pos2 = std::find_if(diffs.begin() + 1, diffs.end(), [](int x) { return x > 1; });
return *(pos + (pos2 - diffs.begin() - 1)) + 1;
}
}
int main() {
std::vector<int> x{ 13, 8, 3, 6, 10, 1,7, 0};
std::cout << find_missing(x, 0) << "\n";
std::cout << find_missing(x, 6) << "\n";
}
template <typename T>
T find_missing(const vector<T>& v, T elem){
vector<bool> range(v.size());
elem++;
for_each(v.begin(), v.end(), [&](const T& i){if((i >= elem && i - elem < range.size())range[i - elem] = true;});
auto result = distance(range.begin(), find(range.begin(), range.end(), false));
return result + elem;
}