Is binary search for an ordered list O(logN) in Elixir? - time-complexity

For an ordered list, the binary search time complexity is O(logN). However in Elixir, the list is linked list, so in order to get the middle element of the list, you have to iterate N/2 times, which make the overall search O(NLogN).
So my question is:
Is above time complexity correct?
If it's correct, the binary search wouldn't make sense in Elixir, right? You have to iterate the list to get what you want, so the best is O(N).

Yes, there is little reason to binary search over a linked list because of the reason you stated. You need a random access data structure (usually an array) for binary search to be useful.
An interesting corner case might arise where the comparison of the elements is very costly, because for example they are just handles to remotely stored items. In that case binary search through a linked list might still outperform linear search, because while requiring more operations (O(N * log(N))) it requires less comparisons (O(log(N))) while linear search requires O(N) comparisons.

Related

Does it make sense to use big-O to describe the best case for a function?

I have an extremely pedantic question on big-O notation that I would like some opinions on. One of my uni subjects states “Best O(1) if their first element is the same” for a question on checking if two lists have a common element.
My qualm with this is that it does not describe the function on the entire domain of large inputs, rather the restricted domain of large inputs that have two lists with the same first element. Does it make sense to describe a function by only talking about a subset of that function’s domain? Of course, when restricted to that domain, the time complexity is omega(1), O(1) and therefore theta(1), but this isn’t describing the original function. From my understanding it would be more correct to say the entire function is bounded by omega(1). (and O(m*n) where m, n are the sizes of the two input lists).
What do all of you think?
It is perfectly correct to discuss cases (as you correctly point out, a case is a subset of the function's domain) and bounds on the runtime of algorithms in those cases (Omega, Oh or Theta). Whether or not it's useful is a harder question and one that is very situation-dependent. I'd generally think that Omega-bounds on the best case, Oh-bounds on the worst case and Theta bounds (on the "universal" case of all inputs, when such a bound exists) are the most "useful". But calling the subset of inputs where the first elements of each collection are the same, the "best case", seems like reasonable usage. The "best case" for bubble sort is the subset of inputs which are pre-sorted arrays, and is bound by O(n), better than unmodified merge sort's best-case bound.
Fundamentally, big-O notation is a way of talking about how some quantity scales. In CS we so often see it used for talking about algorithm runtimes that we forget that all the following are perfectly legitimate use cases for it:
The area of a circle of radius r is O(r2).
The volume of a sphere of radius r is O(r3).
The expected number of 2’s showing after rolling n dice is O(n).
The minimum number of 2’s showing after rolling n dice is O(1).
The number of strings made of n pairs of balanced parentheses is O(4n).
With that in mind, it’s perfectly reasonable to use big-O notation to talk about how the behavior of an algorithm in a specific family of cases will scale. For example, we could say the following:
The time required to sort a sequence of n already-sorted elements with insertion sort is O(n). (There are other, non-sorted sequences where it takes longer.)
The time required to run a breadth-first search of a tree with n nodes is O(n). (In a general graph, this could be larger if the number of edges were larger.)
The time required to insert n items in sorted order into an initially empty binary heap is On). (This can be Θ(n log n) for a sequence of elements that is reverse-sorted.)
In short, it’s perfectly fine to use asymptotic notation to talk about restricted subcases of an algorithm. More generally, it’s fine to use asymptotic notation to describe how things grow as long as you’re precise about what you’re quantifying. See #Patrick87’s answer for more about whether to use O, Θ, Ω, etc. when doing so.

What is wrong with this P argument

My teacher made this argument and asked us what could be wrong with it.
for an array A of n distinct numbers. Since there are n! permutations of A,
we cannot check for each permutation whether it is sorted, in a total time which
is polynomial in n. Therefore, sorting A cannot be in P.
my friend thought that it just should be : therefore sorting a cannot be in NP.
Is that it or are we thinking to easily about it?
The problem with this argument is that it fails to adequately specify the exact problem.
Sorting can be linear-time (O(n)) in the number of elements to sort, if you're sorting a large list of integers drawn from a small pool (counting sort, radix sort).
Sorting can be linearithmic-time (O(nlogn)) in the number of elements to sort, if you're sorting a list of arbitrary things which are all totally ordered according to some ordering relation (e.g., less than or equal to on the integers).
Sorting based on a partial order (e.g. topological sorting) must be analyzed in yet another way.
We can imagine a problem like sorting whereby the sortedness of a list cannot be determined by comparing adjacent entries only. In the extreme case, sortedness (according to what we are considering to be sorting) might only be verifiable by checking the entire list. If our kind of sorting is designed so as to guarantee there is exactly one sorted permutation of any given list, the time complexity is factorial-time (O(n!)) and the problem is not in P.
That's the real problem with this argument. If your professor is assuming that "sorting" refers to sorting integers not in any particular small range, the problem with the argument then is that we do not need to consider all permutations in order to construct the sorted one. If I have a bag with 100 marbles and I ask you to remove three marbles, the time complexity is constant-time; it doesn't matter that there are n(n-1)(n-2)/6 = 161700, or O(n^3), ways in which you can accomplish this task.
The argument is a non-sequitur, the conclusion does not logically follow from the previous steps. Why doesn't it follow? Giving a satisfying answer to that question requires knowing why the person who wrote the argument thinks it is correct, and then addressing their misconception. In this case, the person who wrote the argument is your teacher, who doesn't think the argument is correct, so there is no misconception to address and hence no completely satisfying answer to the question.
That said, my explanation would be that the argument is wrong because it proposes a specific algorithm for sorting - namely, iterating through all n! permutations and choosing the one which is sorted - and then assumes that the complexity of the problem is the same as the complexity of that algorithm. This is a mistake because the complexity of a problem is defined as the lowest complexity out of all algorithms which solve it. The argument only considered one algorithm, and didn't show anything about other algorithms which solve the problem, so it cannot reach a conclusion about the complexity of the problem itself.

Double Ended Singly Linked List - Time complexity of searching

I have read that the time complexity of a searching for an element, which is located at end of the double ended singly linked list is o(N).
But since time complexity of searching for an element at front is o(1), I think the same should apply to end element. Any ideas? Thanks
The cost of searching for an element that is at the front of the linked list is indeed one, because you would be holding a pointer to that first element. Thus, it would be O(1) to find the first element.
In the case of a double ended singly linked list, assuming you mean you hold a pointer to both the first and last element of the singly linked list, you would indeed find that the time to locate the last element would be O(1), because you have a reference to exactly where it is.
However, consider the case of a double ended singly linked list where you want to find the (n-1)th element in that list. Suddenly, you find that you have to iterate over n-1 elements until you get to that element. Thus you would find that the worst case runtime for the double ended singly linked list would be O(n-1), which is really O(n).
Even in the case where you had a double ended doubly linked list, you would find that the worst case runtime would be O(n/2), (assuming you had a mechanism to tell if the element was in the first half of second half, which is unlikely). But O(n/2) is still really O(n).
Since we generally refer to the worst case when we talk about big-o time complexity, you can see that linked lists are invariably O(n).
Note:
That's not to say that big-o is the only measure of time-complexity. Depending on your implementation, the amortized or probabilistic time-complexity could indeed be different from its worst case time complexity, and likely is.

When sequencial search is better than binary search?

I know that:
A linear search looks down a list, one item at a time, without jumping. In complexity terms this is an O(n) search - the time taken to search the list gets bigger at the same rate as the list does.
A binary search is when you start with the middle of a sorted list, and see whether that's greater than or less than the value you're looking for, which determines whether the value is in the first or second half of the list. Jump to the half way through the sublist, and compare again etc.
Is there a case where the sequencial/linear search becomes more eficient than Binary Search ?
Yes, e.g. when the item you are looking for happens to be one of the first to be looked at in a sequential search.

For performing less no of search operations out of a large elements, which searching technique is good enough such that the elements are not sorted?

Lets say,
I have 1000 elements in a array and I want to search 10 elements in that array,then which searching mechanism is most appropriate?
Also , if in case , I need to search 900 elements from the same array,then what search method is good one?
Linear or Binary search ?
Thanks in advance.
If the elements aren't sorted, then you can't do a binary search. But binary search is so much faster than linear search (you'd need to look at an average of 10 elements rather than 500) that you'd be best sorting your list (using an algorithm such as quicksort) and then doing a binary search.