There are a few things to point out:
- Are there duplicates in the input lists?
- Should a result be ordered?
I assume that using std::list you can cheaply insert into the head or tail.
Suppose that there are N elements in list 1 and there are M elements in list 2.
Algorithm 1
It iterates over each element of list 1 that searches for it in list 2.
Assuming there may be duplicates and that a result should be ordered, the worst time to search is that list 2 does not have an element in list 1, therefore it is at least:
To insert an element of list 1 at the desired location, you need to repeat list 2 again to the insertion point. The worst case scenario is when each item in list 1 is less (if the search in list 2 starts from the very beginning) or more (if the search in list 2 is performed from the end). Since the previous elements of list 1 were inserted into list 2, for the first element there would be iterations M, M + 1 for the second, M + 2 for the third, etc. And M + N - 1 iterations for the latter, for the average value of M + (N - 1) / 2 per element.
Something like:
To denote a large O, constant factors do not matter, therefore:
For recordings with large conclusions, unimportant additions do not matter, therefore:
Addition to the original O (N Γ M):
- O (N Γ M) + O (N Γ (M + N))
- O (N Γ M) + O (N Γ M + N 2 )
The second equation is to make obvious the elimination of a constant factor, for example. 2 Γ (N Γ M), thus:
- O (N Γ (M + N))
- O (N 2 + N Γ M)
These are the two equivalents that you like the most.
Possible optimization:
If the result does not need to be ordered, the insert can be O (1), so the worst case of time is:
- Do not just check every element of List 1 in list 2 on an equal basis, check if every element, for example. more so that you can stop searching in list 2 if the item in list 1 is larger than the item in list 2; it would not reduce the worst case, but it would reduce the average case
Keep a List 2 iterator that indicates that the List 1 element was found more than the List 2 element to make the sorted insert O (1); when inserting, be sure to save the iterator that begins with the inserted element, because although list 1 is ordered, it may contain duplicates; with these two, the worst case of time:
For the following iterations, find the List 1 element in the rest of List 2 with the iterator saved; this reduces the worst case, because if you reach the end of list 2, you will simply βdeleteβ duplicates from list 1; with these three, the worst case of time:
At this point, the only difference between this algorithm and Algorithm 2 is that List 2 is modified to contain the result, rather than creating a new list.
Algorithm 2
This is a merge sort merge.
You will move each element of list 1 and each element of list 2 once, and the insert is always performed at the beginning or at the end of the list, so the worst time is:
If there are duplicates, they are simply discarded. The result is easier to streamline than not.
Concluding observations
If there are no duplicates, in both cases the insert can be optimized. For example, with doubly linked lists, we can easily check whether the last item in list 1 is larger than the first item in list 2 or vice versa, and simply combine the lists.
This can be further generalized for any tail of list 1 and list 2. For example, in Algorithm 1, if the List 1 element is not found in list 2, we can combine list 2 and the tail of list 1. In Algorithm 2, this is done in the last step.
The worst case is when the elements of list 1 and the elements of list 2 alternate, do not decrease, but again the average case decreases, and in many cases a big factor that is of great importance in Real Life β’.
I ignored:
- Distribution time
- Heavy gaps in algorithms
- Binary search because you mentioned lists , not arrays or trees
I hope I have not made a blatant mistake.