【问题标题】:How can I print all unused elements?如何打印所有未使用的元素?
【发布时间】:2021-02-17 16:10:16
【问题描述】:

假设我持有一个大小为n 的数组,并且我定义了一个名为add(i) 的函数,它将索引i 中的元素的值增加一。

如何打印值为0 的所有元素(甚至没有增加)在O(k)k 是这些元素的数量?

【问题讨论】:

  • 由于您标记为 C++,您应该使用标准容器和迭代器。一些容器具有专门的搜索功能。还有一些使用迭代器的标准搜索函数。只需确保容器的迭代器类型(例如随机)与搜索功能所需的类型匹配即可。
  • 听起来像是for-loop man 的工作!
  • 请展示一些真实的代码。 k is the number of those elements?“那些元素”是指所有元素还是只指没有增加的元素?
  • 等一下。 K 是 0 元素的数量还是 k 是全部元素的数量?第一个实际上会很棘手。
  • 也许可以使用std::transform?我建议查看<algorithm> include/header 中的函数。

标签: c++ c algorithm time-complexity


【解决方案1】:

你不能用你当前的数据结构。

有很多选择。

  • 您可以使用以值为键的数组字典。 (那么这只是一个遍历键 0 中的 k 个元素的数组的问题。)
  • 您可以将所有值为零的元素放在首位或最后。
  • 您甚至可以完全避免将值为 0 的元素放入数组中,同时跟踪有多少元素。

【讨论】:

    【解决方案2】:

    时间复杂度取决于输入的大小,而不是输入的具体细节。你不能有任何 O(k),其中 k 是通过迭代 n 来计算的(假设 k

    因此,我们可以推断您必须维护一个完全独立的元数据,它是所有尚未递增的索引的集合。您可以在 O(k) 中输出大小为 k 的集合......几乎可以根据定义输出。

    我们忽略了在 add(i) 的实现中维护该信息的工作,因为您只是要求 O(k) 打印元数据,而不是一开始就收集它。显然这是一个棘手的问题。

    【讨论】:

    • 我不明白,您是在告诉我将所有这些索引保存在一边,但是当一个被更改时,我如何在 O(1) 中删除它?
    • 您可以在 O(k) 中打印大小为 k 的集合。正如我已经说过的,维护它的工作量不是所要求的,因此无关紧要。也根本不可知,因为我们不知道 add() 被调用了多少次。
    • 复杂性是衡量随着您增加某物而扩展某物的方式。那东西可以是任何东西,不一定是数组的大小。 O(k) 完全没问题。
    • @WhiteForce 是的,大概是一组。但是由于 add(i) 被调用的次数未知,所以你不知道那是多少次。但他们没有要求,他们只是询问打印 k 个索引。
    • OP 需要一个特殊的容器,比如区间映射,比如 BOOST::icl::Interval_Map。使用简单的数组不可能完全满足他们的需求。
    【解决方案3】:

    警告:这是基于您对希望打印“已更改”索引(与您问题中的“未更改/零”索引相比)的最高评论。

    这可以在O(k) 时间复杂度和O(2n) 空间复杂度下完成。

    鉴于原始数组 arr[n],我们需要一个额外的数组来跟踪 k 更改的索引。

    无论如何,这是带有随机测试套件的代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    enum {
        n = 100
    };
    
    int opt_s;                              // 0=unsorted, 1=qsort, 2=insertion
    int opt_v;                              // verbose/debug printing
    int opt_n;                              // number of array elements
    int seed;                               // random seed
    
    // node to keep track of changed indexes
    // NOTE: next is only needed for sort mode 2
    typedef struct node node_t;
    struct node {
        int idx;
        node_t *next;
    };
    
    int *arr;                               // original array
    node_t *nzlist;                         // list of changed indexes
    int k;                                  // number of changed indexes
    node_t *head;                           // head of list (sort mode 2)
    
    void
    add(int i)
    {
        int oval = arr[i]++;
        node_t *newnode;
        node_t *cur;
        node_t *prev;
    
        do {
            if (oval)
                break;
    
            if (opt_v)
                printf("add: k=%d i=%d\n",k,i);
    
            newnode = &nzlist[k++];
            newnode->idx = i;
    
            if (opt_s != 2)
                break;
    
            // find sorted insertion point
            prev = NULL;
            for (cur = head;  cur != NULL;  cur = cur->next) {
                if (cur->idx > i)
                    break;
                prev = cur;
            }
    
            newnode->next = cur;
    
            // empty list -- set the head
            if (prev == NULL)
                head = newnode;
    
            // insert before cur
            else
                prev->next = newnode;
        } while (0);
    }
    
    int
    sortcmp(const void *vplhs,const void *vprhs)
    {
        const node_t *lhs = vplhs;
        const node_t *rhs = vprhs;
        int cmpflg;
    
        cmpflg = lhs->idx - rhs->idx;
    
        return cmpflg;
    }
    
    void
    sortlist(void)
    {
    
        qsort(nzlist,k,sizeof(node_t),sortcmp);
    }
    
    void
    print_link(void)
    {
        node_t *cur;
    
        for (cur = head;  cur != NULL;  cur = cur->next)
            printf("%d\n",cur->idx);
    }
    
    void
    print_linear(void)
    {
        node_t *cur;
    
        for (cur = &nzlist[0];  cur < &nzlist[k];  ++cur)
            printf("%d\n",cur->idx);
    }
    
    int
    main(int argc,char **argv)
    {
    
        --argc;
        ++argv;
    
        for (;  argc > 0;  --argc, ++argv) {
            char *cp = *argv;
            if (*cp != '-')
                break;
    
            cp += 2;
            switch(cp[-1]) {
            case 'n':
                opt_n = (*cp != 0) ? atoi(cp) : 300;
                break;
    
            case 's':
                opt_s = (*cp != 0) ? atoi(cp) : 1;
                break;
    
            case 'R':
                seed = (*cp != 0) ? atoi(cp) : 0;
                break;
    
            case 'v':
                opt_v = (*cp != 0) ? atoi(cp) : 1;
                break;
            }
        }
    
        if (opt_n <= 0)
            opt_n = 20;
        printf("n = %d\n",opt_n);
        arr = calloc(opt_n,sizeof(*arr));
        nzlist = calloc(opt_n,sizeof(*nzlist));
    
        if (seed == 0)
            seed = time(NULL);
        printf("R = %d\n",seed);
        srand(seed);
    
        int rounds = rand() % (opt_n / 2);
        for (int iround = 0;  iround < rounds;  ++iround) {
            int idx = rand() % opt_n;
            add(idx);
        }
    
        switch (opt_s) {
        case 0:  // unsorted
            print_linear();
            break;
    
        case 1:  // sorted by qsort
            sortlist();
            print_linear();
            break;
    
        case 2:  // insertion sort in linked list
            print_link();
            break;
        }
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 1970-01-01
      • 2013-05-06
      相关资源
      最近更新 更多