Creating List $L_3$ from $L_1,L_2$ w/ $O(n_1+n_2)$ Complexity

In summary: Thinking)So, should it be maybe like that?Solve problem(L1, L2){ pointer L3 ← empty,q=L2; int i,j; for (i=0; i<n2-n1/2-1; i++) q=q->next; for (j=0; j<(n1+n2)/4; j++){ L3->data=L1->next->data; L3=L3->next;
  • #1
evinda
Gold Member
MHB
3,836
0
Hello! (Wave)

Given two lists, $L_1$ with $n_1$ elements and $L_2$ with $n_2$ elements, I want to write an algorithm that creates a new list $L_3$, for which the following stand:

  • The elements at the odd positions of $L_3$ are these that are at the even positions of $L_1$
  • The elements at the even positions of $L_3$ are the last $\frac{n_1}{2}$ elements of $L_2$

$n_1,n_2$ can be any even numbers. The time complexity of the algorithm should be $O(n_1+n_2)$.

Could you give me a hint how I could do this? (Thinking)
 
Technology news on Phys.org
  • #2
evinda said:
Hello! (Wave)

Given two lists, $L_1$ with $n_1$ elements and $L_2$ with $n_2$ elements, I want to write an algorithm that creates a new list $L_3$, for which the following stand:

  • The elements at the odd positions of $L_3$ are these that are at the even positions of $L_1$
  • The elements at the even positions of $L_3$ are the last $\frac{n_1}{2}$ elements of $L_2$

$n_1,n_2$ can be any even numbers. The time complexity of the algorithm should be $O(n_1+n_2)$.

Could you give me a hint how I could do this? (Thinking)

Hi! (Happy)

Alternate between adding even elements from $L_1$ and adding elements of the last $\frac{n_1}{2}$ from $L_2$? (Wondering)

Something like:
Code:
Solve problem(L1, L2)
    L3 ← empty
    Skip the right number of elements in L2
    while not done
        Add next element from L1 to L3
        Skip next element (that is at an odd position) in L1
        Add next element from L2 to L3
    return L3
This will need some refinement though. (Thinking)
 
  • #3
I like Serena said:
Hi! (Happy)

Alternate between adding even elements from $L_1$ and adding elements of the last $\frac{n_1}{2}$ from $L_2$? (Wondering)

Something like:
Code:
Solve problem(L1, L2)
    L3 ← empty
    Skip the right number of elements in L2
    while not done
        Add next element from L1 to L3
        Skip next element (that is at an odd position) in L1
        Add next element from L2 to L3
    return L3
This will need some refinement though. (Thinking)

Can we skip the right number of elements in L2, like that? :confused:
Code:
Solve problem(L1, L2)
    pointer L3 ← empty,p=L1,q=L2;
    int i;
    for (i=0; i<n1; i++) q=q->next

(Thinking)
 
  • #4
evinda said:
Can we skip the right number of elements in L2, like that? :confused:
Code:
Solve problem(L1, L2)
    pointer L3 ← empty,p=L1,q=L2;
    int i;
    for (i=0; i<n1; i++) q=q->next

(Thinking)

That would skip the first $n_1$ entries in $L_2$.
... but we need the last $\frac {n_1}2$ entries, while the total number of entries is $n_2$. (Worried)
So I think we should skip only $n_2 - \frac {n_1}2$ entries. (Thinking)
 
  • #5
I like Serena said:
That would skip the first $n_1$ entries in $L_2$.
... but we need the last $\frac {n_1}2$ entries, while the total number of entries is $n_2$. (Worried)
So I think we should skip only $n_2 - \frac {n_1}2$ entries. (Thinking)

So, should it be like that? (Thinking)

Code:
Solve problem(L1, L2){
    pointer L3 ← empty,q=L2;
    int i,j;
    for (i=0; i<n2-n1/2; i++) q=q->next;
    for (j=0; j<(n1+n2)/2; j++){
         L3->data=L1->next->data;
         L3=L3->next;
         L3->data=q->data;

    }    
    return L3;
}
Or have I done something wrong? (Thinking)
 
  • #6
evinda said:
Code:
Solve problem(L1, L2){
    pointer L3 ← empty,q=L2;
    int i,j;
    for (i=0; i<n2-n1/2; i++) q=q->next;
    for (j=0; j<(n1+n2)/2; j++){
         L3->data=L1->next->data;
         L3=L3->next;
         L3->data=q->data;

    }    
    return L3;
}

Suppose we pick L1={1,2} and L2={7,8}, can you predict what your algorithm will do? (Wondering)
 
  • #7
I like Serena said:
Suppose we pick L1={1,2} and L2={7,8}, can you predict what your algorithm will do? (Wondering)

The first element of $L_3$ will be 1, and the second will be NULL, right? (Thinking)

So, should it be maybe like that?

Code:
Solve problem(L1, L2){
    pointer L3 ← empty,q=L2;
    int i,j;
    for (i=0; i<n2-n1/2-1; i++) q=q->next;
    for (j=0; j<(n1+n2)/4; j++){
         L3->data=L1->next->data;
         L3=L3->next;
         L3->data=q->next->data;

    } 
    L3->next=NULL;   
    return L3;
}

Or am I wrong? :confused:
 
  • #8
evinda said:
The first element of $L_3$ will be 1, and the second will be NULL, right? (Thinking)

So, should it be maybe like that?

Code:
Solve problem(L1, L2){
    pointer L3 ← empty,q=L2;
    int i,j;
    for (i=0; i<n2-n1/2-1; i++) q=q->next;

It looks as if q will be pointer to the right element here. (Smile)
Although I didn't check any potential plus or minus 1 issues yet.
Code:
    for (j=0; j<(n1+n2)/4; j++){

I don't think [m](n1+n2)/4[/m] is the proper end condition.
It may be better to eliminate the end condition here, but check each time we want to process something, check if we can, and if not, take appropriate action. (Thinking)

Typically, we want to check if a pointer is NULL before accessing it.
That is also the right moment to handle the case that it is NULL, and we need to do something special. (Nerd)
Code:
         L3->data=L1->next->data;
         L3=L3->next;

This will cause chaos and madness. (Crying)
The first time round L3 is empty, meaning we cannot access L3->data, nor L3->next.
We can also not be sure that L1->next is different from NULL, so this will also cause an access violation. (Crying)
Code:
         L3->data=q->next->data;

Since neither L1, nor q is ever changed, the same values will be used every time.
I think there should be statements that will bring us to the next element of L1 respectively L2. (Wasntme)
Code:
    } 
    L3->next=NULL;

When we will have constructed L3 properly, it will point to a long linked list.
Assigning L3->next to NULL will effectively throw the whole list away, keeping only the first.
I think that is not right. (Worried)
 

FAQ: Creating List $L_3$ from $L_1,L_2$ w/ $O(n_1+n_2)$ Complexity

What is List $L_3$ and why is it important to create it from $L_1$ and $L_2$?

List $L_3$ is a new list that is created by combining the elements of lists $L_1$ and $L_2$. It is important because it allows us to have a single list containing all the elements from both $L_1$ and $L_2$, which can be useful for further analysis or processing.

What is the complexity of creating List $L_3$ from $L_1$ and $L_2$?

The complexity of creating List $L_3$ from $L_1$ and $L_2$ is $O(n_1+n_2)$, where $n_1$ and $n_2$ are the number of elements in $L_1$ and $L_2$ respectively. This means that the time it takes to create $L_3$ increases linearly with the size of $L_1$ and $L_2$.

What is the advantage of using $O(n_1+n_2)$ complexity for creating List $L_3$?

Using $O(n_1+n_2)$ complexity for creating List $L_3$ ensures that the time it takes to create the list increases at a manageable rate, even for large lists $L_1$ and $L_2$. This allows for efficient processing of the lists without significant time delays.

Can List $L_3$ be created in less than $O(n_1+n_2)$ complexity?

No, List $L_3$ cannot be created in less than $O(n_1+n_2)$ complexity since it requires going through all the elements of both lists $L_1$ and $L_2$ to combine them into a single list. Any algorithm that claims to create $L_3$ in less than $O(n_1+n_2)$ complexity is not feasible.

Are there any drawbacks to using $O(n_1+n_2)$ complexity for creating List $L_3$?

One potential drawback is that if the lists $L_1$ and $L_2$ are already sorted, it may take longer to create $L_3$ using $O(n_1+n_2)$ complexity compared to using a more specific algorithm for merging two sorted lists. In such cases, it may be more efficient to use a different approach for creating $L_3$.

Back
Top