リストをスキャンする前にある程度の前処理が許可されている場合は、予想される数の二重リンクリストを維持する前処理されたデータ構造を作成し、スキャン時にそのリンクリストから要素を削除できます。入力の数字のシーケンス。二重リンクリストに残っているものはすべて、入力から欠落しているものです。
リストのノードは実際には配列から作成されているため、二重リンクリストのメンバーへのアクセスはO(1)です。二重リンクリストからの削除はO(1)です。したがって、欠落している番号は、入力の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]);
}
};