简体   繁体   English

给定一个数组 l1,l2,l3 。 . . ln 创建一个新数组如下: (l1+ln),(l2+l[n-1]), . . .(l[n/2]+l[n/2+1])

[英]Given an array l1,l2,l3 . . . ln create a new array as follow: (l1+ln),(l2+l[n-1]), . . .(l[n/2]+l[n/2+1])

So I have the following problem:所以我有以下问题:

Given an array l1,l2,l3 .给定一个数组 l1,l2,l3 。 . . . . ln, create a new array as follow: (l1+ln),(l2+l[n-1]), . ln,创建一个新数组如下: (l1+ln),(l2+l[n-1]), 。 . . .(l[n/2]+l[n/2+1]). .(l[n/2]+l[n/2+1])。 This problem has the following rules and informations:这个问题有以下规则和信息:

  • The original list must be read one time only.原始列表只能阅读一次。
  • The list is dynamic and has only the value and a pointer to the next item.该列表是动态的,只有值和指向下一项的指针。
  • The new list must be of the same type the original is.新列表的类型必须与原始列表相同。
  • Is not allowed to create an auxiliary list to read the data more than once.不允许创建辅助列表多次读取数据。

I have tried many times to solve it and although i have been close to the solution, the result is still in the wrong order.我已经尝试了很多次来解决它,尽管我已经接近解决方案,但结果仍然是错误的顺序。 Next I show my current test scenario:接下来我展示我当前的测试场景:

struct No
    {
        int Value;
        No* Next;
    };
    typedef No* Noptr;
    
    int main()
    {
        Noptr L = NULL;
        InsertList(L,1);
        InsertList(L,2);
        InsertList(L,3);
        InsertList(L,5);
        InsertList(L,4);
        InsertList(L,3);
        InsertList(L,9);
        InsertList(L,2);
        InsertList(L,7);
        InsertList(L,1);
        InsertList(L,10);
        InsertList(L,12);
        InsertList(L,11);
        InsertList(L,15);
        InsertList(L,19);
        InsertList(L,16);
        Noptr L4 = SumValues(L);
        Lista (L4);
    
        return 0;
    }
    
    
    Noptr SumValues(Noptr& L)
    {
        if(L == NULL){
            return L;
        }
        Noptr L1 = NULL;
        Noptr L2 = NULL;
        Noptr aux1 = L;
        bool Even= false;
        while(aux1 != NULL)
        {
            if(!Even)
            {
                InsertLista(L1,aux1->Value);
            }
            else
            {
                InsertLista(L2,aux1->Value);
            }
            Even = !Even;
            aux1 = aux1->Next;
        }
        L2 = InverterLista(L2);
        Noptr LReturn = NULL;
        aux1 = L1;
        Noptr aux2 = L2;
        while(aux1!= NULL){
            InsertList(LReturn ,(aux1->Value+aux2->Value));
            aux1 = aux1->Next;
            aux2 = aux2->Next;
        }
        free(L1);
        free(L2);
        free(aux1);
        free(aux2);
        return LReturn;
    }

I expected the array: 17, 21, 18, 16, 16, 13, 10, 9;我期望数组: 17, 21, 18, 16, 16, 13, 10, 9; Instead, I got: 17, 18, 16, 10, 9, 13, 16, 21 To visualize better, I created a table相反,我得到了: 17, 18, 16, 10, 9, 13, 16, 21为了更好地可视化,我创建了一个表格

 [00] [01] [02] [03] [04] [05] [06] [07] INDEX

 17   21   18   16   16   13   10   09  EXPECTED

 17   18   16   10   09   13   16   21  RESULT

What I did wrong?我做错了什么?

Algorithm:算法:

  1. Reverse the first half of original list.反转原始列表的前半部分。
  2. Traverse the first half and second half list:遍历前半部分和后半部分列表:
    • Take care of size of list:注意列表的大小:
      • If original list size is odd then middle node value will be last node value of new list.如果原始列表大小为奇数,则中间节点值将是新列表的最后一个节点值。
      • If original list size is even then sum of n/2 th node and n/2 + 1 th node value will be the last node value of new list.如果原始列表大小为偶数,则n/2节点和第n/2 + 1节点值的总和将是新列表的最后一个节点值。 Note that n/2 th node is first node of reversed list and n/2 + 1 th node first node of second half list.请注意,第n/2节点是反向列表的一个节点,n/2 + 1节点是后半列表的一个节点。
    • Add the value of both list node and assign this value to the new list node.添加两个列表节点的值并将此值分配给新的列表节点。 Move to the next node in both the list.移动到两个列表中的下一个节点。
    • Add every node of new list node to the head of new list.将新列表节点的每个节点添加到新列表的头部。
  3. Repeat step 2 until either of the list pointer reach to nullptr .重复第 2 步,直到任一列表指针到达nullptr
  4. Reset the original list to its original form (reverse the first half again).将原始列表重置为其原始形式(再次反转前半部分)。

Implementation:执行:
(not pure object oriented implementation but enough to understand) (不是纯面向对象的实现,但足以理解)

#include <iostream>
#include <cstdlib>

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x):val(x),next(nullptr){}
    ~ListNode(){/*take care of deallocation*/}
};

struct ListNode * getNode(int x) {
    struct ListNode *temp = new ListNode(x);
    if (temp == nullptr) {
        exit (EXIT_FAILURE);
    }

    return temp;
}

void insert(int d, struct ListNode ** head) {
    struct ListNode *temp = getNode(d);

    if (temp == nullptr) {
        exit (EXIT_FAILURE);
    }

    struct ListNode **curr = head;
    while (*curr) {
        curr = &((*curr)->next);
    }

    *curr = temp;
}

// Algorithm implementation
struct ListNode * sumValues(struct ListNode *head){
    int odd = 0;
    struct ListNode *slowPtr = head;
    struct ListNode *fastPtr = head;
    struct ListNode *newList = nullptr;
    struct ListNode *prev = nullptr;

    // Reverse first half of original list
    while (fastPtr) {
        fastPtr = fastPtr->next;
        if (!fastPtr) {
            odd = 1;
            break;
        }
        fastPtr = fastPtr->next;
        struct ListNode *curr = slowPtr->next;
        slowPtr->next = prev;
        prev = slowPtr;
        slowPtr = curr;
    }

    struct ListNode *L1 = prev;
    struct ListNode *L2 = nullptr;
    L2 = slowPtr;

    // The middle node of original list will be last node of new list if orignal list has odd number of nodes
    if (odd) {
        L2 = L2->next;
        newList = getNode(slowPtr->val);
    }

    // Traverse both first half (reversed) and second half of original list and prepare new list
    while (L2) {
        struct ListNode *tmp = getNode(L1->val + L2->val);
        tmp->next = newList;
        newList = tmp;
        L2 = L2->next;
        L1 = L1->next;
    }

    // Reset the original list
    struct ListNode *tmp = prev;
    prev = slowPtr;
    while (tmp) {
        struct ListNode *curr = tmp->next;
        tmp->next = prev;
        prev = tmp;
        tmp = curr;
    }

    return newList;
}

void printList(struct ListNode * newList, struct ListNode *origList) {
    struct ListNode *x = origList;
    std::cout << "\nPrint lists\n";
    std::cout << "Original list : ";
    while (x) {
        std::cout << x->val << " ";
        x = x->next;
    }

    std::cout << "\n"; 
    x = newList;
    std::cout << "Sum List : ";
    while (x) {
        std::cout << x->val << " ";
        x = x->next;
    }

    std::cout << "\n"; 
}

// Driver code
int main() {
    struct ListNode *head = nullptr;
    struct ListNode *newList = nullptr;

    insert (1, &head);
    // list =>  1 -> null
    newList = sumValues(head);
    printList(newList, head);

    insert (2, &head);
    // list =>  1 -> 2 -> null
    newList = sumValues(head);
    printList(newList, head);

    insert (3, &head);
    // list => 1 -> 2 -> 3 -> null 
    newList = sumValues(head);
    printList(newList, head);

    insert (4, &head);
    // list =>  1 -> 2 -> 3 -> 4 -> null
    newList = sumValues(head);
    printList(newList, head);

    insert (5, &head);
    // list =>  1 -> 2 -> 3 -> 4 -> 5 -> null
    newList = sumValues(head);
    printList(newList, head);

    insert (4, &head);
    // list =>  1 -> 2 -> 3 -> 4 -> 5 -> 4 -> null
    newList = sumValues(head);
    printList(newList, head);

    insert (2, &head);
    // list =>  1 -> 2 -> 3 -> 4 -> 5 -> 4 -> 2 -> null
    newList = sumValues(head);
    printList(newList, head);

    insert (4, &head);
    // list =>  1 -> 2 -> 3 -> 4 -> 5 -> 4 -> 2 -> 4 -> null
    newList = sumValues(head);
    printList(newList, head);

    insert (1, &head);
    // list =>  1 -> 2 -> 3 -> 4 -> 5 -> 4 -> 2 -> 4 -> 1 -> null
    newList = sumValues(head);
    printList(newList, head);

    // Make sure to deallocate both the list

    return 0;
}

Output:输出:

# ./a.out

Print lists
Original list : 1 
Sum List : 1 

Print lists
Original list : 1 2 
Sum List : 3 

Print lists
Original list : 1 2 3 
Sum List : 4 2 

Print lists
Original list : 1 2 3 4 
Sum List : 5 5 

Print lists
Original list : 1 2 3 4 5 
Sum List : 6 6 3 

Print lists
Original list : 1 2 3 4 5 4 
Sum List : 5 7 7 

Print lists
Original list : 1 2 3 4 5 4 2 
Sum List : 3 6 8 4 

Print lists
Original list : 1 2 3 4 5 4 2 4 
Sum List : 5 4 7 9 

Print lists
Original list : 1 2 3 4 5 4 2 4 1 
Sum List : 2 6 5 8 5 

If its not allowed to manipulate original list then you can use stack to prepare sum list.如果不允许操作原始列表,则可以使用堆栈来准备总和列表。 Algorithm using stack :使用堆栈的算法

  1. Push the first half original list to stack.将前半个原始列表压入堆栈。
  2. Traverse the second half of original list:遍历原始列表的后半部分:
    • Take care of size of list:注意列表的大小:
      • If original list size is odd then middle node value will be last node value of new list.如果原始列表大小为奇数,则中间节点值将是新列表的最后一个节点值。
      • If original list size is even then sum of n/2 th node and n/2 + 1 th node value will be the last node value of new list.如果原始列表大小为偶数,则n/2节点和第n/2 + 1节点值的总和将是新列表的最后一个节点值。 Note that n/2 th node is first node of stack and n/2 + 1 th node first node of second half list.请注意,第n/2节点是堆栈的一个节点,n/2 + 1节点是后半列表的一个节点。
    • Pick top value from stack and add with the value of current node of second half list and assign to new list node.从堆栈中选择顶部值并与后半列表的当前节点的值相加并分配给新的列表节点。 Pop value from stack and move pointer of second half to its next .从堆栈中弹出值并将后半部分的指针移动到next .
    • Add every node of new list node to the head of new list.将新列表节点的每个节点添加到新列表的头部。
  3. Repeat step 2 until stack empty or second half traversal pointer reach to nullptr .重复步骤 2 直到堆栈为空或后半遍历指针到达nullptr

Algorithm using doubly ended queue :使用双端队列的算法

  1. Take a doubly ended queue.采取双端队列。
  2. Traverse whole list and push the elements of list at the back of queue.遍历整个列表并将列表的元素推到队列的后面。
  3. Pop element from front and back of queue, add them and assign this value to the value of node to be added to the tail of new list.从队列的前后弹出元素,添加它们并将该值赋给要添加到新列表尾部的节点的值。
  4. Repeat step 3 until queue will be empty.重复步骤 3,直到队列为空。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM