具有两个定义的操作的随机访问循环数据结构

时间:2016-11-20 16:49:14

标签: c algorithm

作为输入,我会看到一个自然整数列表。 我必须将它们存储在一个结构中,使我能够从最后一个元素转到第一个元素而没有太多问题。

任务是在此数据结构上执行t(从头开始给出的数字)操作。从作为输入的第一个数字开始(i = 0):

如果data [i]%2 == 0 - >执行操作R

其他 - >执行操作X

操作R:删除索引位置为i + 1的元素,并向右移动与删除元素的值一样多次。

操作X:获取data [i]元素的值,并在值为data [i] -1的前面插入新元素。然后向右移动数据[i]。

示例(i-> n表示我指向具有值n的el。):

输入:3 1 2 3

t = 3

data = [1,2,3]

 1.
 i->1
 operation X, 
 result: [ 1, 0, 2, 3 ]

 2.
 i->0
 operation R,
 result: [ 1, 0, 3 ]

 3.
 i->1
 operation X, 
 result: [ 1, 0, 0, 3 ]

当t的值非常大时,会出现真正的问题。 我试过两个实现:

  • 一个基于链表。我知道它有效,因为结果是正确的,但执行时间接近2-3分钟。
  • 一个基于数组,但执行时间稍快一点。

这个片段需要99.99%的执行时间:

while(t--){
    c = current -> value;
    if(c % 2 == 0){
        c = current -> next -> value;
        Node* n = current -> next -> next;
        free(current -> next);
        current -> next = n;

        --size;
    }
    else{
        Node* n = getNode(current -> next);
        current -> next = n;
        n -> value = c-1;

        ++size;
    }

    c %= size;
    while(c--){
        current = current->next;
    }
}

getNode(Node * n)返回带节点的新节点 - > next = n。

对优化方法/其他方法有任何了解。

*编辑:

Node* getNode(Node* nxt){
    Node* first = (Node*)malloc(sizeof(Node));
    first -> value = -1;
    first -> next = nxt;
    return first;
}

2 个答案:

答案 0 :(得分:0)

根据算法运行时间思考(其中n是元素的长度):

  • 您需要t次操作,因此外部循环为O(n)
  • 如果你使用链接列表,找到ith元素是O(n)并移动ith元素是Theta(1),因为你只是改变指针使你的内部while循环{{1}所以O(n)
  • 的总运行时间
  • 使用数组,找到ith元素为O(n^2)但是移动它们是Theta(1),因此内部循环再次为O(n),总数为O(n)

你能使用带有整数索引的hashmap作为键和值,就好像它是一个链表吗? Hashmaps会同时进行搜索并移动O(n^2)进行总计Theta(1)

答案 1 :(得分:0)

还有一些观察结果:

  • 数据结构可以增长。
  • 对于每个奇数true,意味着插入X语句(R将是偶数)。
  • '中间结果的最大尺寸'是data[i]-12 * N是原始输入中的元素数(当输入只是奇数时)。

的优化:

  1. 因此,您可以使用结构数组进行优化,因此您无需调用N。相反,在每个结构中使用一些簿记状态将元素标记为活动/非活动。可能只是检查值free()以确定它是否有效/无效。您需要在导航/搜索代码中对此进行补偿,因为现在您需要的不仅仅是简单的模运算,以便从当前索引导航到下一个元素。缺点是这会使>= 0更加昂贵,因为导航到前一个元素也是如此。
  2. 您可以通过跟踪当前索引的先前位置来进一步减少数组中的搜索行为。这有助于避免因步骤#1而导致实施X的惩罚。
  3. 您可以通过检查外部循环中X是否size >= 0进行简单优化,因为如果while(t--)size之前是{0},那么无论如何都是你。< / LI>