I am learning about BIG-O and got confused below:
int arr=[1,2,3,4,5]
-- simple print
print(arr[0])
print(arr[1])
print(arr[2])
print(arr[3])
print(arr[4])
-- loop - BIG-O O(n)
for i in length(arr) {
print( arr[i] )
}
would the simple print also give me O(n) or O(1) ?
Big-O is all about loops and growth.
If you have a fixed n then it is O(1) to print them — it will always take the same amount of time (n=5) to print n=5 items.
But for some variable n, it takes more time the larger n gets, so it becomes O(n).
If you are talking about storage, then an array of n items is O(n), even for fixed n=5.
Context matters. This context was me being stupid. O(5) is O(1).
Your print statement is constant (O(1)), because you are accessing a value by index, and indexed access of an array is typically a constant-time operation.
Your loop is O(n), as you guessed. So your code in total would also be O(n), since the loop performs a constant action.
As a disclaimer, this can get more complex depending on our computation model and assumptions. For instance, not all computation model assume constant-time random access, and you could argue that printing a number also depends on the size of that number and turns out to be O(log n). But I think that in the scope of your question, you don't need to worry about this.
Related
I am working on creating an algorithm of time complexity O(n) to sort an array by only switching the prefix values. For example, to sort the array 3,4,1,2 the procedure would look like:
3,4,1,2
4,3,1,2
2,1,3,4
3,1,2,4
2,1,3,4
1,2,3,4
Each time I bring the largest value of the array that is not in the right position to the front of the array then flip only up to the point that is not sorted to bring the largest value of that portion of the array to the end. Intuitively, I believe this would not be a time complexity of O(n) but I am not sure how to find the right the time complexity. My thought process so far is since there is an n+1 amount of operations being done on the array the constant would drop so it would have a time complexity of O(n). Is my thinking correct?
You are correct that there is an n+1 amount of operations being done on the array, however one of these operations itself has a time complexity of O(n) - this is the searching for the highest value which requires checking every element in the list.
Since checking for the highest value in the list happens on every loop, and the algorithm would have to loop n times, this results in a time complexity of at least O(n^2).
I sometimes get confused with the time complexity analysis for the code that includes arrays.
For example:
ans = [0] * n
for x in range(1, n):
ans[x] = ans[x-1] + 1
I thought the for-loop had a time complexity of O(n^2) because it accesses elements in the array with n elements, and it repeats the same thing for n times.
However, I've seen some explanations saying it takes just O(n); thus, my question is: when we analyze the time complexity of a program that accesses elements in an array (not necessarily the first or the last element), should we include the time to access those array elements, or is it often ignored?
Indexed access is usually a constant-time operation, due to the availability of random access memory in most practical cases. If you were to run this e.g. in Python and measure the time it takes for different values of n, you will find that this is the case.
Therefore, your code only performs one loop from 1 to n and all other operations are constant-time, so you get a time complexity of O(n).
Your thinking is otherwise right - if this was a linked list and you had to iterate through it to find your value, then it would be O(n2).
time complexity
Big-O cheat sheet
Supposed an array is initially empty with a size 5, and it expands by 5 everytime all slots are filled.
I understand that if we are only considering any sequence of n append() operations, the amortized cost would be O(n) because the total cost would be:
5+(5+1*5)+(5+2*5)+...+(5+(floor(n/5)-1)*5) = O(n^2).
*where floor(n/5) is the number of array expansions.
However, what if it's any sequence of n operations contains pop() as well? Assume pop() doesn't change array size.
My way obviously wouldn't work and I have read the CLRS but am still quite stucked. Any help would be appreciated.
The answer, somewhat disappointingly, is if your sequence contains s many push or pop operations then the amortized cost of each operation is O(s).
To cherry-pick a line from another question's very good answer:
Amortized analysis gives the average performance (over time) of each operation in the worst case.
The worst case is pretty clear: repeated pushes. In which case, your original analysis stands.
The question is pretty much what the title says, with a slight variation. If I remember correctly, finding an entry in an array of size 'n' has as the average case the complexity O(n).
I assume that is also the case if there is a fixed number of elements in the vector, of which we want to find one.
But how is it if the amount of entries, of which we still only try to find one, is in some way related to the size of the vector, i.e. grows in some way with it?
I have such a case at hand, but I don't know the exact relation between array size and number of searched-for entries. Might be linear, might be logarithmically.. Is the average case still O(n)?
I would be grateful for any insights.
edit: an example
array size: 100
array content: at each position, a number of 1-10, completely random which one.
what we seek: the first occurrence of "1"
from a naive point of view, we should on average find an entry after 10 lookups in any kind of linear searches (which we have to do, as the content is not sorted.)
As factors are usually omitted in big-O, does that mean that we still need O(n) in time, even though it should be O(n)
It is O(n) anyway.
Think about finding 1 here:
[9,9,9,9,9,1]
If you're doing a linear search through the array, then the average time complexity of finding one of M elements in an array with N elements will be O(I) where I is the average index of the first of the sought elements. If the array is randomly ordered, then I will be O(N/M) on average, and so the time complexity will also be O(N/M) on average and O(N-M) in the worst case.
I have two minds over this question.
First, if you'll consider an unsorted array (which the case seems here), the asymptotic complexity for average case will be surely O(n).
Let's take an example.
We have n elements in the array or better to say Vector. Now,average case will be searching in a linear fashion by node to node. Which appears to be n/2 in general for average or O(n) as an average case. See,if the elements are added, then the complexity's nature won't change but, the effect is clear,it's n/2 comparisons for average---which is directly 1/2 (half) of n. The effect for m elements now after insertion in array will be O(n-m),or in comparison wise,(n-m)/2 comparisons added as a result to addition of elements in the Vector!
So,we find that with increase in size of array or better to say Vector---the complexity's nature won't change though the no. of comparisons required would be more as it is equal to n/2 in average case.
Second, if the array or vector is sorted, then performing binary-searches will have worst-cases of order log(n+1)---again dependent on n. Also, the average case will increase the comparisons logarithmically,but the complexity order O(log n) won't change!
I am having trouble on an assignment regarding running time.
The problem statement is:
"Isabel has an interesting way of summing up the values in an array A of n integers, where n is a power of two. She creates an array B of half the size of A, and sets B[i] = A[2i] + A[2i+1], for i=0,1,…,(n/2)-1. If B has size 1, then she outputs B[0]. Otherwise, she replaces A with B, and repeats the process. What is the running time of her algorithm?"
Would this be considered a O(log n) or a O(n)? I am thinking O(log n) because you would keep on dividing the array in half until you get the final result and I believe the basis of O(log n) is that you do not traverse the entire data structure. However in order to compute the sum, you have to access each element within the array thus making me think that it could possibly be O(n). Any help in understanding this would be greatly appreciated.
I believe the basis of O(log n) is that you do not traverse the entire
data structure.
There's no basis for beliefs or guesses. Run through the algorithm mentally.
How many recursions are there going to be for array A of size n?
How many summations are there going to be for each recursion (when array A is of size n)?
First run: n/2 summations, n accesses to elements of A
.
.
.
Last run: 1 summation, 2 accesses to elements of A
How many runs are there total? When you sum this up, what is the highest power of n?
As you figured out yourself, you do need to access all elements to compute the sum. So your proposition:
I believe the basis of O(log n) is that you do not traverse the entire data structure
does not hold. You can safely disregard the possibility of the algorithm being O(log n) then.
As for being O(n) or something different, you need to think about how many operations will be done as a whole. George Skoptsov's answer gives a good hint at that. I'd just like to call attention to a fact (from my own experience) that to determine "the running time" you need to take everything into account: memory access, operations, input and output, etc. In your simple case, only looking at the accesses (or the number of sums) might be enough, but in practice you can have very skewed results if you don't look at the problem from every angle.