如果std::set
或std::list
包含一系列自然数(1,2,3 ......)。标准库中是否有一个函数可以找到丢失的数字?
答案 0 :(得分:6)
你可以std::mismatch()
使用一系列自然数。为了节省空间,我认为boost::counting_iterator
可以在这里创造奇迹:
#include <iostream>
#include <list>
#include <boost/iterator/counting_iterator.hpp>
int main()
{
std::list<int> l = {1,2,3,4,6,7,8,9};
auto i = mismatch(l.begin(), l.end(), boost::counting_iterator<int>(1));
if(i.first==l.end())
std::cout << "no missing numbers\n";
else
std::cout << "the first missing number is " << *i.second << '\n';
}
试运行:
~ $ g++ -std=c++0x -pedantic -Wall -Wextra -o test test.cc
~ $ ./test
the first missing number is 5
答案 1 :(得分:4)
您可以使用set_difference和自定义迭代器找到所有缺失的数字:
class seqIter : public std::iterator<std::input_iterator_tag, int> {
public:
seqIter(int n) : num(n) {}
seqIter(const seqIter & n) : num(n.num) {}
int & operator *() {return num;}
seqIter & operator ++() { ++num; return *this; }
bool operator !=(const seqIter & n) { return n.num != num; }
private:
int num;
};
int main(int argc, char *argv[])
{
int n[] = { 1, 3, 4, 7, 10 };
std::set<int> numbers(n, n + sizeof(n)/sizeof(n[0]));
std::set<int> missing;
std::set_difference( seqIter(*numbers.begin()+1), seqIter(*numbers.rbegin()),
numbers.begin(), numbers.end(),
std::insert_iterator<std::set<int> >(missing, missing.begin())
);
}
这可能不比通过for循环通过数字更快。
答案 2 :(得分:3)
没有专门用于此目的(标准算法试图更加概括)。但是,您可以使用std::accumulate
作为相当大的一部分工作。
提示:1..N中一组数字的总和为(N + 1)*(N / 2)。
编辑:我对答案的想法是,如果所有数字都存在,则从你得到的总和中减去你所拥有数字的总和。这种差异将是缺失的数字。
#include <numeric>
#include <iostream>
#define elements(x) (sizeof(x)/sizeof(x[0]))
int main() {
int x[] = {8, 4, 3, 5, 1, 2, 7};
int N = elements(x) +1;
int projected_sum = (N+1)*(N/2);
int actual_sum = std::accumulate(x, x+elements(x), 0);
std::cout << "The missing number is: " << projected_sum - actual_sum << "\n";
return 0;
}
目前,这忽略了一些细微的细节,例如如果集合具有奇数个元素会发生什么,但应该显示一般的想法。我还使用了数组而不是列表,只是为了便于初始化。我没有使用列表不能(合理地)支持的随机访问。这具有线性复杂性,正如您从示例输入中看到的那样,不需要对输入进行排序。
Edit2:如果意图是输入按排序顺序,我可能会稍微改变一下这个工作:只需走过去找一个不比它的前任更大的项目。