如果在扫描列表之前允许您进行一些预处理,那么您可以拥有一个预处理数据结构,该结构维护您期望拥有的数字的双向链表,并在扫描时从该链表中删除元素输入中的数字序列。双向链表中剩下的就是输入中缺少的。
对双向链表中成员的访问是 O(1),因为列表的节点实际上是从数组创建的。从双向链表中删除是 O(1)。因此,在输入的单遍中找到丢失的数字。复杂度为 O(i+m),其中 i 是输入的大小,m 是缺少多少个数字。
下面的代码根据输入将与之进行比较的序列的起始值和结束值创建双向链表。使用它就像:
Tracker t(0, 10);
int i;
while (std::cin >> i) t.remove(i);
t.report();
享受!
struct Node {
static int index;
static int stop;
int num;
struct Node *next;
struct Node *prev;
Node () : num(index++), next(0), prev(0) {
if (index <= stop) next = this + 1;
if (index > 0) prev = this - 1;
}
};
struct Tracker {
int start;
int finish;
Node *nodes;
Tracker (int s, int f) : start(s), finish(f) {
if (finish < start) throw 0;
Node::index = start;
Node::stop = finish + 1;
nodes = new Node[finish - start + 2];
nodes[finish - start + 1].next = nodes;
nodes[0].prev = &nodes[finish - start + 1];
}
~Tracker () { delete[] nodes; }
void remove (int i) {
Node *n = &nodes[i - start];
n->prev->next = n->next;
n->next->prev = n->prev;
}
void report () {
Node *n = nodes[finish - start + 1].next;
if (n->next == n) std::cout << "all there" << std::endl;
else do {
std::cout << "missing: " << n->num << std::endl;
n = n->next;
} while (n != &nodes[finish - start + 1]);
}
};