What is the big O notation and how do I calculate it? - algorithm

Calculate big o of function. How do I calculate the big O notation in this function?
Example:
function fun1(int n)
{
int s = 0;
for(int i = 0; s < n; i++)
{
s += i;
for(var j = s; j < n; j++)
{
console.log(j);
}
}
return s;
}

Roughly speaking, consider the i-th iteration of the outer loop. After execution of the loop's body,
s = 1 + 2 + ... + i-1 + i
which is equal to i*(i+1)/2 = (i²+i)/2 by an identity by Gauss. The maximum value for i such that this expression is smaller than n is can be obtained by elementary calculation as follows. If we require
(i²+i)/2 <= n
which means
i²+i-2n <= 0
we can use the formula for reduced quadratic equation to obtain
i <= -1/2 + sqrt(1/4+2n)
which is in O(n^{1/2}). In each iteration of the outer loop, the inner loop takes n-s iterations, which very roughly can be estimated by n (but this is very imprecise, I believe the overall analysis can be made more precise). In total, this yields a bound of O(n^{1/2}*n)=O(n^{3/2}).

Related

Three summations intertwined of a code: counting number of primitive operations & big O notation

I have the following code: I need to get the big O notation and calculate the number of primitive operations. I know that loops usually corresponds to mathematical summations. Can someone help out clarify how to solve the Big O the following code, knowing the summations?
public static int hello(int[] first, int[] second) { // assume equal-length arrays
int n = first.length, count = 0;
for (int i = 0; i < n; i++) { // loop from 0 to n-1
int total = 0;
for (int j = 0; j < i; j++) {// loop from 0 to i
for (int k = 0; k <= j; k++) { // loop from 0 to j
total += first[k];
}
}
if (second[i] == total) {
count++;
}
}
return count;
}
So this would be
right? How do you continue from here?
When running the code with n=10, the first loop runs n times i.e. 10 times, a statement at the level of the second loop runs 45 times, don't know what that means in terms of n and a statement with constant time at the level of the inner third loop runs 165 times.
Can someone help me with what type of summations this code would be and how it translates to Big O? Thank you so much for any help.
Sum of first n natural numbers and sum of squares of first n natural numbers is given as ,
You have got the right summation, so solving it
Sn =
Sn ≤
Sn ≤
Sn ≤
Sn translates to number of operations performed by the for loops altogether.
Time complexity is thus givens as,
O(Sn) ~ O(n3)

Big-O analysis for a loop

I've got to analyze this loop, among others, and determine its running time using Big-O notation.
for ( int i = 0; i < n; i += 4 )
for ( int j = 0; j < n; j++ )
for ( int k = 1; k < j*j; k *= 2 )`
Here's what I have so far:
for ( int i = 0; i < n; i += 4 ) = n
for ( int j = 0; j < n; j++ ) = n
for ( int k = 1; k < j*j; k *= 2 ) = log^2 n
Now the problem I'm coming to is the final running time of the loop. My best guess is O(n^2), however I am uncertain if this correct. Can anyone help?
Edit: sorry about the Oh -> O thing. My textbook uses "Big-Oh"
First note that the outer loop is independent from the remaining two - it simply adds a (n/4)* multiplier. We will consider that later.
Now let's consider the complexity of
for ( int j = 0; j < n; j++ )
for ( int k = 1; k < j*j; k *= 2 )
We have the following sum:
0 + log2(1) + log2(2 * 2) + ... + log2(n*n)
It is good to note that log2(n^2) = 2 * log2(n). Thus we re-factor the sum to:
2 * (0 + log2(1) + log2(2) + ... + log2(n))
It is not very easy to analyze this sum but take a look at this post. Using Sterling's approximation one can that it is belongs to O(n*log(n)). Thus the overall complexity is O((n/4)*2*n*log(n))= O(n^2*log(n))
In terms of j, the inner loop is O(log_2(j^2)) time, but sine
log_2(j^2)=2log(j), it is actually O(log(j)).
For each iteration of middle loop, it takes O(log(j)) time (to do the
inner loop), so we need to sum:
sum { log(j) | j=1,..., n-1 } log(1) + log(2) + ... + log(n-1) = log((n-1)!)
And since log((n-1)!) is in O((n-1)log(n-1)) = O(nlogn), we can conclude middle middle loop takes O(nlogn) operations .
Note that both middle and inner loop are independent of i, so to
get the total complexity, we can just multiply n/4 (number of
repeats of outer loop) with complexity of middle loop, and get:
O(n/4 * nlogn) = O(n^2logn)
So, total complexity of this code is O(n^2 * log(n))
Time Complexity of a loop is considered as O(n) if the loop variables is incremented / decremented by a constant amount (which is c in examples below):
for (int i = 1; i <= n; i += c) {
// some O(1) expressions
}
for (int i = n; i > 0; i -= c) {
// some O(1) expressions
}
Time complexity of nested loops is equal to the number of times the innermost statement is executed. For example the following sample loops have O(n²) time complexity:
for (int i = 1; i <=n; i += c) {
for (int j = 1; j <=n; j += c) {
// some O(1) expressions
}
}
for (int i = n; i > 0; i += c) {
for (int j = i+1; j <=n; j += c) {
// some O(1) expressions
}
Time Complexity of a loop is considered as O(logn) if the loop variables is divided / multiplied by a constant amount:
for (int i = 1; i <=n; i *= c) {
// some O(1) expressions
}
for (int i = n; i > 0; i /= c) {
// some O(1) expressions
}
Now we have:
for ( int i = 0; i < n; i += 4 ) <----- runs n times
for ( int j = 0; j < n; j++ ) <----- for every i again runs n times
for ( int k = 1; k < j*j; k *= 2 )` <--- now for every j it runs logarithmic times.
So complexity is O(n²logm) where m is n² which can be simplified to O(n²logn) because n²logm = n²logn² = n² * 2logn ~ n²logn.

worst case runtime of the double for loop

Can someone please explain how the worst case running time is O(N) and not O(N^2)in the following excercise. There is double for loop, where for every i we need to compare j to i , sum++ and then increment and again repeat the operation until reach N.
What is the order of growth of the worst case running time of the following code fragment
as a function of N?
int sum = 0;
for (int i = 1; i <= N; i = i*2)
for (int j = 0; j < i; j++)
sum++;
Question Explanation
The answer is : N
The body of the inner loop is executed 1 + 2 + 4 + 8 + ... + N ~ 2N times.
I think you already stated the answer in your question -- the inner loop is executed 2N times, which is O(N). In asymptotic (or big-O) notation any multiples are dropped because for very, very large values, the graph of 2N looks just like N, so it isn't considered significant. In this case, the complexity of the problem is equal to the number of times "sum++" is called, because the algorithm is so simple. Does that make sense?
Complexity doesn't depends upon number of nested loops
it is O(Nc):
Time complexity of nested loops is equal to the number of times theinnermost statement is executed.For example the following sample loops have O(N2) time complexity
for (int i = 1; i <=n; i += c) {
for (int j = 1; j <=n; j += c) {
// some O(1) expressions
}
}
for (int i = n; i > 0; i += c) {
for (int j = i+1; j <=n; j += c) {
// some O(1) expressions
}

Troubles with Big O Estimate

I'm asked to give a big-O estimates for some pieces of code but I'm having a little bit of trouble
int sum = 0;
for (int i = 0; i < n; i = i + 2) {
for (int j = 0; j < 10; j + +)
sum = sum + i + j;
I'm thinking that the worst case would be O(n/2) because the outer for loop is from i to array length n. However, I'm not sure if the inner loop affects the Big O.
int sum = 0;
for (int i = n; i > n/2; i − −) {
for (int j = 0; j < n; j + +)
sum = sum + i + j;
For this one, I'm thinking it would be O(n^2/2) because the inner loop is from j to n and the outer loop is from n to n/2 which gives me n*(n/2)
int sum = 0;
for (int i = n; i > n − 2; i − −) {
for (int j = 0; j < n; j+ = 5)
sum = sum + i + j;
I'm pretty lost on this one. My guess is O(n^2-2/5)
Your running times for the first two examples are correct.
For the first example, the inner loop of course always executes 10 times. So we can say the total running time is O(10n/2).
For the last example, the outer loop only executes twice, and the inner loop n/5 times, so the total running time is O(2n/5).
Note that, because of the way big-O complexity is defined, constant factors and asymptotically smaller terms are negligible, so your complexities can / should be simplified to:
O(n)
O(n2)
O(n)
If you were to take into account constant factors (using something other than big-O notation of course - perhaps ~-notation), you may have to be explicit about what constitutes a unit of work - perhaps sum = sum + i + j constitutes 2 units of work instead of just 1, since there are 2 addition operations.
You're NOT running nested loops:
for (int i = 0; i < n; i = i + 2);
^----
That semicolon is TERMINATING the loop definition, so the i loop is just counting from 0 -> n, in steps of 2, without doing anything. The j loop is completely independent of the i loop - both are simply dependent on n for their execution time.
For the above algorithms worst case/best case are the same.
In case of Big O notation, lower order terms and coefficient of highest order term can be ignored as Big O is used for describing asymptotic upper bound.
int sum = 0;
for (int i = 0; i < n; i = i + 2) {
for (int j = 0; j < 10; j + +)
sum = sum + i + j;
Total number of outer loop iteration =n/2.for each iteration of outer loop, number of inner loop iterations=10.so total number of inner loop iterations=10*n/2=5n. so clearly it is O(n).
Now think about rest two programs and determine time complexities on your own.

How to calculate Time Complexity for a given algorithm

i, j, N, sum is all integer type. N is input.
( Code1 )
i = N;
while(i > 1)
{
i = i / 2;
for (j = 0; j < 1000000; j++)
{
sum = sum + j;
}
}
( Code2 )
sum = 0;
d = 1;
d = d << (N-1);
for (i = 0; i < d; i++)
{
for (j = 0; j < 1000000; j++)
{
sum = sum + i;
}
}
How to calculate step count and time complexity for a Code1, Code2?
to calculate the time complexity try to understand what takes how much time, and by what n are you calculating.
if we say the addition ("+") takes O(1) steps then we can check how many time it is done in means of N.
the first code is dividing i in 2 each step, meaning it is doing log(N) steps. so the time complexity is
O(log(N) * 1000000)= O(log(N))
the second code is going form 0 to 2 in the power of n-1 so the complexity is:
O(s^(N-1) * 1000000)= O(2^(N-1))
but this is just a theory, because d has a max of 2^32/2^64 or other number, so it might not be O(2^(N-1)) in practice

Resources