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

时间:2012-06-11 00:03:39

标签: c++ performance algorithm data-structures

我正在尝试为这个问题实现一个有效的解决方案,“假设在一个从1到n的未排序数组中,如果删除了一个数字怎么会找到,如果删除了n个数字怎么办?”

让我说一下,我对编码没有任何麻烦,如果有人可以提供我的基本想法,我就在这里。我想,将所有元素存储在散列表中,索引是数字本身(即散列(1)= 1),稍后从1到n检查散列表是否存在。这将花费 O(n)时间。如果删除多个号码,我当然会提出这个建议。对于值,我将计算从1到n的n之和,并减去数组的总和。

然而,对于移除的n号,我可以添加任何效率。 (如果数字虽然我的解决方案是存储像(O(12)= 12 = -12),基本链接但自动将时间复杂度增加到O(2n)。这个问题实际上是我之所以会问这个问题,但是对于唯一的积极因素仍然有任何想法也可以提供帮助。)

4 个答案:

答案 0 :(得分:2)

你的解决方案是最好的,你不能有更好的复杂性然后O(N)(O(2N)实际上是O(N))如果你有一个好的函数,如果你有负数并不重要映射你的价值。对于数字我会建议一个低于n的数字并且是一个素数,让我们称这个数字为P. f(x)= x%P(对于值x,键将是x%P) 对于P = 9913,我们应该: hash [10] = 10,9923,-9903并且所有具有(它们的值)%P的数字等于数组中的10。  您可以使用链接列表或向量来消除冲突。 对于数字Y,您应该将Y存储在索引Y%P处,并且在范围(1..n)中对于i进行一次遍历,您应该查看位于i的P的哈希表中的i(基本上是O(1) )查询的复杂性)就是这样。希望它有所帮助。 对不起我的英文:(

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

for i=0 to n:
    bools[values[i]] = True:
for i=0 to n:
    if(bools[i] == False):
        print("%d is missing".format(i))

如果给出负值,首先遍历数组并找到最低值。如果是-10,则为每个值加10,所以-10将转到位置0.然后使用上面的逻辑,当你找到负值时,减去10。

“假设在1到 n 的未排序数组中,如果删除了一个数字,如果 n 数字被删除了怎么办?”

如果 n 数字被删除,则数组将不包含任何值。

答案 3 :(得分:0)

如果在扫描列表之前允许进行一些预处理,那么您可以使用预处理的数据结构来维护您希望拥有的数字的双向链接列表,并从该链接列表中删除元素当您扫描输入中的数字序列时。无论在双向链表中剩下什么,输入中缺少的是什么。

对双向链表中的成员的访问是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]);
    }
};