Why the Big-O is O(n) and not O(n/2) of this code - time-complexity

I am trying to understand the Big-O of algorithms.
I found this code online and I wasn't able to understand how the Big-O was calculated for it:
void printFirstItemThenFirstHalfThenSayHi100Times(int arr[], int size)
{
printf("First element of array = %d\n",arr[0]); % O(1)
for (int i = 0; i < size/2; i++) % O(n/2)
{
printf("%d\n", arr[i]);
}
for (int i = 0; i < 100; i++) % O(100), which is a constant
{
printf("Hi\n");
}
}
It says (big-o-with-examples) that, the big-O is O(N)! why?
I see that we have a constant at the beginning O(1), then O(n/2), and finally O(100). Why the Big-O is O(N) and not O(N/2)?

Because Big-O(n) == Big-O(1/2 * n), drop the constant factor.
See Is there such a thing as O(n/2) in Big O notation?

Related

Time complexity of for loop with if/else

Would the following code be considered O(1) or O(n)? The for loop has constant complexity which runs 10 times but I'm not sure whether the if condition would be considered O(n) or O(1).
for (i = 0; i < 10; i++)
{
if (arr [i] == 1001)
{
return i;
}
}
The complexity would be O(1), because regardless of how much you increase the input the complexity of the algorithm remains constant. Namely, the operations performed inside that loop are considered to have constant time, hence O(1).
for (i = 0; i < 10; i++)
{
if (arr [i] == 1001)
{
return i;
}
}
On the other hand if your loop was:
for (i = 0; i < 10; i++)
{
f(n)
}
and the function f(n) had a complexity of O(n) then the complexity of the entire code snippet would be O(n) since 10 * N can be labeled as O(n).
For a more in depth explanation have a look at What is a plain English explanation of “Big O” notation?

Calculating Big O and time complexity of code as a linked list vs array based

Hi I'm trying to calculate the big O notation of this code, assuming the list that is being used is a linked list
public static void update(List<Star> list) {
// compute and apply acceleration
for (int i = 0; i < list.size(); i++) {
Star s1 = list.get(i);
for (int j = i + 1; j < list.size(); j++) {
Star s2 = list.get(j);
Vector acceleration = attractionAcceleration(s1, s2);
s1.velocity.add(acceleration);
acceleration.negate();
s2.velocity.add(acceleration);
}
}
// apply velocity
for (int i = 0; i < list.size(); i++) {
Star s = list.get(i);
s.location.add(s.velocity);
}
}
}
I was also asked to calculate the big O assuming the list is an array based list and I got O(N^2) due to it being 2 nested loops. I have been told that the answer for it as a linked list is O(N^4), i'm just not sure how I explain either of these calculations completely
When calculating the linked list, remember that list.get is O(N). So for the first two lines of your code, you have O(N^2) for lists and O(N) for arrays.
for (int i = 0; i < list.size(); i++) { O(N) for both
Star s1 = list.get(i); O(N) for list, O(1) for array
for (int j = i + 1; j < list.size(); j++) { O(N) for both
Star s2 = list.get(j); O(N) for list, O(1) for array
}
}
So you have two extra O(N) for lists. The nested for loops multiply, and Star s1... adds, since it is not in the internal loop, giving O(N^3) for the acceleration phase.

How to proof the time complexity of this Fibonacci sequence is O(n)

In the following code, i know that the time complexity is O(n) but how do i proof it in a proper way?
Is saying that searching array is O(n) enough?
int f[N];
F(n)
{
if (f[n] >= 0) return f[n];
f[n] = F(n-1) + F(n-2);
return f[n];
}
int main()
{
read n;
f[0] = 0; f[1] = 1;
for (i = 2; i <= n; i++)
f[i] = -1;
print F(n);
}
For each element of the array you call F. it may seem as a recursion to you but a bad implementation. each of the f[n-1] and f[n-2] calls actually just returns the values.
You will have 3n call to F(n), so still O(n).
If you are not obligated to recursion, you can program it with a single loop.

time complexity ( studying for exam)

I am currently studying to an examen in algorithms and I am trying to solve a question about time complexity in java, but can't really figure out how to do it. I am suppose to calculate the expected time complexity. N is a positive integer.
for (int i=0; i < N; i++)
for (int j=i+1; j < N; i++) {
int x=j+1; int h=N-1; int k;
while(x<h) {
k=(x+h)/2;
if (a[i]+a[j]+a[k] == 0) { cnt++; break;}
if (a[i]+a[j]+a[k] < 0) x=k+1;
else h=k-1;
}}
The first for loop should run N times and the second should run N-1. Since x is j+1 I guessed that x= N-2. I dont know how to think after that with the while loop or if I have done anything right. Would really appreciate help!
Create your time complexity function in parts.
for (int i=0; i < N; i++) //Takes linear O(n)
for (int j=i+1; j < N; i++) { //Takes linear O(n) and in computer science we can safely assume -1 is irrelevant at N-1 in big O notation
int x=j+1; int h=N-1; int k; // 3 x O(1)
while( x < h ) { // Worst case is when j equals i + 1 where i = 0 so x is at lowest 2 and h equals to N-1 so h depends on N. So again loop takes linear O(n) time.
k=(x+h)/2; // Takes O(1) time
if (a[i]+a[j]+a[k] == 0) { // Takes O(1) time and if this gives true we do break from the while loop
cnt++; // Takes O(1) time
break; // Takes O(1) time
}
if ( a[i]+a[j]+a[k] < 0 ) { // Takes O(1) time
x=k+1; // Takes O(1) time
} else {
h=k-1; // Takes O(1) time
}
}
}
}
So in summary T(N) equals to O(N^3) and Ω(N^2)
More specific T(N) = N * N-1 * N-2 + 10 and this last while loop in avarage takes O(N/2) time but still in computer science it is same as O(N).
We are only interested in worst and best cases.
To confuse even more big O notation actually
T(N)=O(g(N)) means this:
I hope this answer helps even little bit...

My quicksort crashes on already sorted data

I wanted to check the performance time for different data in array (random, already sorted, sorted in descending order).
void Quicksort(int *T, int Lo, int Hi)
{
if (Lo<Hi){
int x=T[Lo];
int i=Lo, j=Hi;
do
{
while (T[i] < x) ++i;
while (T[j] > x) --j;
if (i<=j)
{
int tmp = T[i];
T[i] = T[j];
T[j] = tmp;
++i; --j;
}
} while(i < j);
if (Lo < j) Quicksort(T, Lo, j);
if (Hi > i) Quicksort(T, i, Hi);
}
}
Here are the functions used to generate and fill the testing array:
int* createArr(int length){
int* Arr= new int[length];
return Arr;
}
void Random(int *A, int length){
for (int i=0;i<length;i++){
A[i]=rand();
}
}
void Order(int *A, int length){
for (int i=0;i<length;i++){
A[i]=i;
}
}
void Backwards(int *A, int length){
for (int i=0;i<length;i++){
A[i]=length-i;
}
}
It works fine for random numbers, but when I try to fill it in ascending order and sort, it crashes with stack overflow. Can anyone give me a hint of why is it happening?
When you choose the [Lo] item as a partioning value (a pivot), and the array is already sorted, then you get a partitioning 1 to (length–1). This causes the next (recursive) call on a longer part of the array to handle just one item less then the previous level. So, as #AlexanderM noted, you will get as deep into the recursion as the length of your array. If the array is big, it will almost certainly cause the stack overflow.
Try using a tail reursion: check which part is shorter and sort it with a resursive call, then continue on the current level with the longer part. To do that replace the very first if with while and replace
if (Lo < j) Quicksort(T, Lo, j);
if (Hi > i) Quicksort(T, i, Hi);
with
if (j-Lo < Hi-i)
{
Quicksort(T, Lo, j);
Lo = i;
}
else
{
Quicksort(T, i, Hi);
Hi = j;
}
This won't make the program any faster – it will still need O(n^2) time on an already-sorted array, but will protect against linear stack memory usage, keeping it at worst O(log n).
For further directions concerning better performance see Wikipedia article Quicksort, part Choice of pivot.