I am having a hard time getting the complexity of this for-loop
for (i = 4; i < n; i++)
{
for (j = i - 3, sum = a[i - 4]; j <= i; j++)
{
sum += a[j];
}
System.out.println("sum thru" + i + ": " + sum);
}
I was thinking that the complexity of this nested loop is n^2 since it's a nested loop
but someone told me that this is incorrect and nested loops aren't always a quadratic complexity!
I don't really know how to get the complexity in a good way. I've seen lots of articles about Big-O and complexity but they weren't helpful because they were expecting me to know everything, and they examples weren't the same as any of the examples I have.
I am not asking for the answer, I'm asking for the method. Is there any formula or method that will work for everything in this topic? I want to know how to get the number of assignments but unfortunately I have no clue how to do this.
Can someone explain it to me step by step?
You can see the outer loop iterates (n-4) times, since it is starting with 4 and condition is less than only. The inner loop will iterate maximum of 4 times. Because it starts with i-3 and ends in i. So the complexity is 4*(n-4). Hence the complexity is O(n).
I don't think there is any formula that can solve all problems regarding to time complexity of algorithms. For me, the best way to figure out the big-O is going step by step, from the outer process to the inner process. I believe it is also the standard way for a beginner like you and me. For your question, first, the outer loop is O(n), which is straight forward. Then inside each loop, we have an inner process, which is another loop. That loop goes from i-3 to i, which is O(1). Then inside that process, it is a normal assignment statement, which is O(1) again.
We take all together, the big-O will be O(n) * O(1) * O(1) = O(n)
Related
Im working on a research paper about quicksort for school and thus I have to make a precise runtime analysis on best and worst case for my algorithm but im struggling with the part of my while-statements. I understand why its log(n) since you have so many recursive calls that you have n/2^k = 1 and this equation gives you n = 2^k, k = log2(n) and so on ... well since i did understand the recursive calls this part does not really matter but what matters is my following code:
}
}
I have to specify the "cost" for each statement in dependence of my elements n.
So i added a +1 for every if statement since they are simple statements and now i dont now how to get the cost for the while loops. The outer loop runs until the pointers i and j cross so the outer loop gets execuated at least n/2+1 (+1 for the exit condition) - but i cant find out how often the inner two while loops run. I thought that they would run also n/2 times but this cant work since our teacher taught us that we have to multiply the costs whenever we have nested statements which would result in a (n/2+1)*((n/2)+1)+((n/2)+1)) which is clearly n^2 and not O(n) ...
And yes i have to add a +1 for each abort condition and if statement altough they dont really matter ...
I hope you can help me by telling me whats my mistake that i get a O(n^2) runtime although it has to be O(n)
Side note: I think for the while-loops it doesnt matter if its the best or worst case so dont mind that
Thanks in advance
ChampSilver
The reason why the worst case run time is O(n) is that if you have a careful look at the code, you realize that you visit each array index at most once:
observe that index i only increases at size, and index j only decrease, therefore you'll go at most once over each index.
For example, if you have an array a[] of size 10, then the initial index i will be 0, and j will be 9. x will be (randlomly) somewhere in between, let's say x=4.
Then, the outer while loop enters, and the first inner while loop increases index i until a[i] >= a[x].
The second inner while loop does the same to index j, for the opposite direction.
But the sum of total iterations of both inner loops is at most 10. At which point the next outer while loop check will return false and no second iteration will occur.
Lets start with this:
our teacher taught us that we have to multiply the costs whenever we have nested statements which would result in a (n/2+1)*((n/2)+1)+((n/2)+1)) which is clearly n^2 and not O(n)
This is only true if the looping variables in inner and outer loops are independent of each other.
eg.
for i in range(1..10):
for j in range(1..10):
do something
This is because, for every value of i, inner loop iterates for all values of j. So, this is O(n^2). Now, lets look the other example:
for i in range(1..10):
for i in range(1..10):
do something
In this case, the outer loop runs only once as when inner loop exits, condition for outer loop also discontinues. So, this is, O(n).
Now, lets look at your while loops.
The outer condition is while i is less than j. Inside, we are always incrementing i and decreasing j. So, in this case, the total number of times while statements (all 3) are executed will be the upper bound on i + j, which is 2n. So, complexity is O(2n) or, O(n).
EDIT:
I am making this edit to explain what "complexity" means, practically.
It is a way of approximating/calculating, number of iterations that are made in total, all loops and instructions combined, as size of input increases. So, if you really want to know that, just assign a variable, say a and add 1 to a as the 1st line of every loop. Then print a for different input sizes and you will know what O() notation means, theoretically vs practically.
public static void findNumber(int number) {
int[] soretedArray = { 1, 5, 6, 8, 9 };
for (int i = 0; i <= soretedArray.length; i++) {
for (int j = i + 1; j < soretedArray.length; j++) {
if (soretedArray[i] + soretedArray[j] == number) {
System.out.println(soretedArray[i] + "::" + soretedArray[j]);
return;
}
}
}
}
Using this code I am able to find the number and its complexity is O(N^2) but I have to find this using O(N) complexity i.e using only one for loop or hash-map or similar in Java.
I remember, I was watching the official Google video about this problem. Although it is not demonstrated in java, it is explained step-by-step in different variations of the problem. You should definitely check it:
How to: Work at Google — Example Coding/Engineering Interview
As explained in the Google video that Alexander G is linking to, use two array indexes. Initialize one to the first element (0) and the other to the last element (sortedArray.length - 1). In a loop, check the sum of the two elements at the two indexes. If the sum is the number you were looking for, you’re done. If it’s too high, you need to find a smaller number at one of the indexes; move the right index one step to the left (since the array is sorted, this is the right way). If on the other hand, the sum you got was too low, move the left index to the right to obtain a higher first addend. When the two indexes meet, if you still haven’t found the sum you were looking for, there isn’t any. At this point you have been n - 1 times through the loop, so the algorithm runs in O(n).
We ought to first check the precondition, that the array is really sorted. This too can be done in O(n), so doing it doesn’t break any requirements.
The algorithm may need refinement if you are required to find all possible pairs of numbers that yield the desired sum rather than just one pair.
Is this answer superfluous when the video link has already said it? For one thing, my explanation is shorter, so if it suffices, you’re fine. Most importantly, if the video is removed or just moved to another URL, my answer will still be here.
With fixed number, for any chosen x in the array you just have to find if number-x is in the array (Note that you can also bound x). This will not give you O(n), but O(n.log(n)).
Maybe by remarking that if you have a_i and a_j (j>i), taking the sum and comparing against number, if the result is greater next interesting tests are with a_(i-1) or a_(j-1), and if result is lower next interesting tests are with a_(i+1) or a_(j+1), will give hint to linear-time?
I need to understanding the algorithm for insertion sort.
If someone can explain in layman terms how this code breaks down.
public void insertionSort() {
int in, out;
for(out=1; out<nElems; out++) {
long temp = a[out];
in = out;
while(in>0 && a[in-1] >= temp){
a[in] = a[in-1]; // shift item right,
--in;
a[in] = temp; } // end for
I would like to know in particular why
What i do not understand is, in other sorts we use the for loop, and in this one we are using while loop in this particular sort?
2.a[in-1] >= temp, are they using this because we have removed one element?
What i do not understand is, in other sorts we use the for loop, and
in this one we are using while loop in this particular sort?
Humm no. Some sort implementations don't even have a loop. In this particular case they use a while loop because the number of iterations is not known in advance, but in Java the for loop can do the exact same things as a while loop so it's just a matter of readability
a[in-1] >= temp, are they using this because we have removed one
element ?
Because they perform a shift, which is always done by storing one of the shifted elements in a temporary variable. This is probably the most classical programming trick :
a = 5, b = 6
tmp = a
b = a
a = tmp
// now a is 6 and b is 5
while loops and for loops are (essentially) equivalent, because you can always do:
for(int i = 0; i < n; i++)
as
int i = 0
while (i < n) {
...
i++;
}
(The scope of int i is a little different e.g. in Java because in for loops its scope of i is only inside the the loop.)
It is not. The algorithm is trying to move the current value backwards in the array.
I think the Wikipedia article and this picture inside it is very helpful in understanding the concept.
Well, depending on how a while loop is structured, it can serve the same purpose as for loop. Additionally, most sorts utilize recursion. My advice to you is
1) Look up insertion sort, basic enough but look at a visual representation and analyze what is being done. That'll help you understand what is going on in the code.
2) Think about the run time (which is O(n^2) average case). Why is it O(n^2)? What does this mean?
I have just started solving Topcoder algorithm problems and have written this algorithm for SRM 466 Div 2 LotteryTicket problem in Java.
As I am not good with time complexity so if somebody could explain me how to calculate time complexity for this algorithm step by step.
public static String buy1(int price,int...b){
int sum=0; String stat="IMPOSSIBLE";
for(int i=0;i<b.length;i++)
sum=sum+b[i];
if(sum==price)
return "POSSIBLE";
if(b.length>1){
stat=buy1(price,Arrays.copyOfRange(b,0,b.length-1));
stat=buy1(price,Arrays.copyOfRange(b,1,b.length));
}
return stat;
}
For your case , The recurrence relation is
(let b.length() be bn)
___________buy1(p,bn-1) (as (b,0,b.length-1) equivalent is bn-1 in number )
/
buy1(p,bn) ____/
\
\___________ buy1(p,bn-1) (as (b,1,b.length) equivalent is bn-1 in number )
So our problem for n = two sub-problem of n-1 hence our time function T(n) is as follows
T(n)=2T(n-1)+c (For convenience lets eliminate c as it is very less compared to T(n) for this instance )
T(n)=2[2(T(n-2))]
T(n)=2{2[2(T(n-3))]} ===> 2poweri(T(n-i)) -------- equation(1)
The recurrence ends when it meets base condition . Lets say T(0)=c(be base condition) that means t(n-i)=t(0) for base condition .so i=n
Substituting i value in equation(1) we get 2power(n){t(0)}
So our Time function value will be 2power(n) and our complexity of program is equal to bigoh(2power(n))
You can use the recursion tree method and master method to find the complexity.
Check this out for more ideas on how to approach this problem.
As an additional exercise try computing the complexity of merge sort using this.
Interesting question. Lets calcluate it correctly ;)
So we will check the worst situation when condition (sum == price) will never appear.
First let's check complecity when b.length = 1. Then you should use only only one "=" operation inside the cycle:
for(int i=0;i<b.length;i++)
And 2 inside initialization:
int sum=0; String stat="IMPOSSIBLE";
Next step. Lets calculate this task for N.
First you need to do N "=" operations inside first the cycle, 2 inside initialization and 2 operations inside if.
stat=buy1(price,Arrays.copyOfRange(b,0,b.length-1));
stat=buy1(price,Arrays.copyOfRange(b,1,b.length));
Another operations are made inside recursive step. So we can use recurrent formula for this situation, which equals:
f(n) = 4 + n + 2*f(n-1), f(1) = 3
Solution of this equation is:
f(n) = -6+5 * 2^n-n
So complecity of your algo is exponential. O(2^n)
I am ignoring all another operations, except "=" because they will not change asymptotic complexity.
what is the complexity of a program having only one loop, is it log n?
can someone give me some ideas about estimating complexity of codes?
Well, that really depends on what is going on in that loop.
This loop is linear time, i.e., O(n):
int sum = 0;
foreach( int i in SomeCollection )
{
sum += i;
}
However, consider a loop which performs a substring search during each iteration. Now you have to consider the complexity of the string searching algorithm. Your question can't be answered as it stands. You will need to provide a code sample if you want a meaningful answer.
Software Complexity
There is a field of study that attempts to quantify exactly that.
It's called cyclomatic complexity.
In this case, I believe your complexity rating would be p = 2, because the loop is conditional and that means there are two paths through the method.
Time complexity
If you are referring to time complexity, it's still just O(1) unless the loop iteration count is derived via a polynomial or exponential function, perhaps indirectly because the method is itself called in a higher loop, or because the loop counter is effectively multiplied by string operations or something at a lower level.
To get the Big-O complexity of a piece of code, you need to ask yourself "how many iterations are done"?
The problem is of course, that it isn't always easy to figure it out from the code itself, sometimes it's just better to look at the big picture and calculate the amount of operations done.
Examples:
For (i = 0 ; i < n ; i++ ) {
//Do stuff
}
This is a complexity
For (i = n ; i > 0 ; i= i/2 ) {
//Do stuff
}
This is a complexity... Because in each iteration i is cut in half.
void Mess (int n) {
for (i = 0 ; i < n ; i++) {
//Do stuff
Mess(n-1);
}
}
Now this looks like a simple loop, nut because it calls itself with recursion, it's actually quite a mess.... Each iteration calls itself n times with n-1.
So here it would be easier to think from the end. If n == 1 , there's 1 iteration. If n == 2 then it calls the previous scenario twice.
So if we'll call the function , we can see what we'll get this recursively:
Which in the end will of course give us n!
Bottom line, it's not always trivial.
If there's just one loop, it's probably the number of times that loop's body executes.... But of course you may have many hidden loops in library calls. It's easy to make a loop that executes n times O(n^2) or worse if you have strlen, memcpy, etc. taking place inside the loop body.
Or even worse, if you have a library (or language) with regular expressions and their regex implementation is naive (like Perl), it's easy to make a program with just a single loop O(2^n)!! This cannot happen with a correctly written regex implementation.
You can easily predict the computation time and complexity of your code with some tools such as "trend-prof"(https://pdfs.semanticscholar.org/8616/7f320e230641299754e0fbd860c44f5895f0.pdf)
For the same purpose on R codes, the GuessCompx library available in Github.
If it is Big-O time complexity you are asking about, then for loop it is n times complexity of whatever is within the loop, where n is loop count limit.
So. if the code inside loop is taking constant time to execute, i.e. if its time complexity is O(1), then the complexity of the loop will be O(1*n) = O(n).
In the similar way, if within the loop you have another loop which will make m steps, then your entire code is O(n*m), and so on.