简体   繁体   中英

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 . . . ln, create a new array as follow: (l1+ln),(l2+l[n-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; Instead, I got: 17, 18, 16, 10, 9, 13, 16, 21 To visualize better, I created a table

 [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. Note that n/2 th node is first node of reversed list and n/2 + 1 th node first node of second half list.
    • 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 .
  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. Note that n/2 th node is first node of stack and n/2 + 1 th node first node of second half list.
    • 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 .
    • 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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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