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

Finding one and N elements removed from an unsorted array

本文关键字:一个 元素 排序 数组 删除 查找      更新时间:2023-10-16

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

让我说一下,我在编码方面没有问题,如果有人能贡献我的基本想法,我就在这里。我想,将所有元素存储在一个哈希表中,索引是数字本身(即 hash(1)=1),然后从 1 到 n 检查哈希表是否存在。这将需要 O(n) 时间。当然,如果删除多个数字,我建议这样做。对于单个值,我将计算从 1 到 n 的编号总和并减去数组的总和。

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

你的解决方案是最好的,你不能有比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 处,并且在 range(1..n) 中对 i 进行一次遍历,您应该在 i%P 的位置查看哈希表,以获取 i( 基本上是 O(1) 查询的复杂性),仅此而已。希望它有帮助。对不起我的英语:(

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

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

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 个数字,则数组将不包含任何值。

如果在扫描列表之前允许您进行一定程度的预处理,那么您可以使用预处理的数据结构来维护您期望具有的数字的双向链表,并在扫描输入中的数字序列时从该链表中删除元素。双链表中剩下的就是输入中缺少的内容。

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