C++ 查找从未排序数组中删除的一个和N个元素

C++ 查找从未排序数组中删除的一个和N个元素,c++,performance,algorithm,data-structures,C++,Performance,Algorithm,Data Structures,我试图为这个问题实现一个有效的解决方案,“假设在一个从1到n的未排序数组中,如何发现一个数字是否被删除,如果n个数字被删除怎么办?” 请允许我指出,我在编码方面没有问题,如果有人能提供我的基本想法,我就在这里。我想,将所有元素存储在一个哈希表中,索引为数字本身(即哈希(1)=1),然后从1到n检查哈希表中是否存在该值。这需要O(n)时间。如果删除一个以上的数字,我当然建议这样做。对于单个值,我将计算从1到n的nums之和,然后减去数组的和 然而,对于删除的n号,我可以添加任何内容来提高效率。(如

我试图为这个问题实现一个有效的解决方案,“假设在一个从1到n的未排序数组中,如何发现一个数字是否被删除,如果n个数字被删除怎么办?”

请允许我指出,我在编码方面没有问题,如果有人能提供我的基本想法,我就在这里。我想,将所有元素存储在一个哈希表中,索引为数字本身(即哈希(1)=1),然后从1到n检查哈希表中是否存在该值。这需要O(n)时间。如果删除一个以上的数字,我当然建议这样做。对于单个值,我将计算从1到n的nums之和,然后减去数组的和


然而,对于删除的n号,我可以添加任何内容来提高效率。(如果涉及负数,尽管我的解决方案是像(O(12)=12=-12)那样存储,但是基本的链接会自动将时间复杂度增加到O(2n)。这个问题实际上是我问这个问题的原因,但是关于唯一正数的任何想法也会有所帮助。)

我认为我们可以为这个问题定义多个数据结构。 例如,定义INT del=0;并定义一个del_列表,del_列表节点可以记录地址和编号;
我们有一个未排序的数组A,如果我们从数组A中删除一个数字,将删除的数字添加到del_列表和del++;所以我们可以知道有多少号码被删除了,它们是什么。此外,如果我们编码,我认为有更有效的方法来解决这个问题,但现在我不知道:P。。我希望这个答案能对您有所帮助。

对于使用哈希表的解决方案,您不需要哈希表。如果您知道值是从1到n,那么可以使用n个大小的布尔数组。只需遍历值数组,使用该值索引到布尔值数组,并将该位置的值设置为True。然后,遍历布尔数组并查找假值,以查看哪些值已被删除。如果使用整数数组并在位位置设置真/假值,则可以使用更少的空间。 这是一个

如果给定的值为负值,请首先通过数组并找到最小值。如果是-10,则将每个值加上10,这样-10将转到位置0。然后使用上述逻辑,当您找到负值时,减去10

“假设在从1到n的未排序数组中,如何查找是否删除了一个数字,以及如果删除了n个数字会怎么样?”


如果删除了编号,数组将不包含任何值。

如果允许在扫描列表之前进行一定量的预处理,则可以使用预处理的数据结构来维护预期编号的双链接列表,当你扫描输入中的数字序列时,你会从链表中删除元素。双链接列表中剩下的就是输入中缺少的内容

对双链接列表中成员的访问权限为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]);
    }
};
struct节点{
静态整数指数;
静态int停止;
int-num;
结构节点*下一步;
结构节点*prev;
节点():num(index++)、next(0)、prev(0){
如果(指数0)prev=this-1;
}
};
结构跟踪器{
int启动;
整饰;
节点*节点;
跟踪器(整数s,整数f):开始(s),结束(f){
如果(完成<开始)掷0;
节点::索引=开始;
节点::停止=完成+1;
节点=新节点[完成-开始+2];
节点[完成-开始+1]。下一步=节点;
节点[0]。上一个=&节点[finish-start+1];
}
~Tracker(){delete[]节点;}
无效删除(int i){
节点*n=&节点[i-开始];
n->prev->next=n->next;
n->next->prev=n->prev;
}
作废报告(){
Node*n=nodes[finish-start+1]。下一步;

如果(n->next==n)std::cout你的解决方案是最好的,你的复杂度再高不过O(n)(O(2N)实际上是O(n)),如果你有一个很好的函数来映射你的值,你是否有负数也没关系。对于数字,我建议一个小于n的数字,作为素数,让我们称它为p。 f(x)=x%P(对于值x,键应为x%P) 对于P=9913,我们应该有: 散列[10]=109923,-9903以及数组中(其值)%P等于10的所有数字。 可以使用链表或向量来消除碰撞。 对于数字Y,您应该将Y存储在索引Y%P处,对于范围(1..n)中的i,您应该在pozition i%P处查找哈希表,对于i(对于查询,基本上是O(1)复杂度),就是这样。希望它有所帮助。
对不起,我说的是英语:(

一个元素是微不足道的:对原始数组中的所有数字执行异或运算,然后在移除元素的数组中执行。最后对两个结果进行异或运算以获得缺失的数字。线性时间,恒定内存要求。移除多个元素如何?多个元素,好吧,这一个不是微不足道的:p我不认为我有我脑子里有一个解决方案:)如果O(n)个解决方案是可以接受的,为什么计算数组中的元素数不足以解决问题?@user315052:问题不在于删除了多少元素,而在于删除了哪些元素。
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]);
    }
};