Counting number of comparisons in code - java

for(int i = 0; i < N * N; i = i + 1)
for(int j = 1; j < i + 1; j = j + 1)
junk = junk + 1;
I need to determine the relationship between the number of < operations executed and N. I should give an exact answer, such as 27N + 18.
Any help is appreciated! Thanks

For the first loop, as you can see i starts from 0 and goes to N^2 -1
1) That means N^2 + 1 times.
For every i, inner loop starts with 1 goes to N^2
2) 1 + 2 + 3 ... (N^2) = N^2 * (N^2 +1 ) / 2 = (N^4 + N^2) / 2
That means, operator "<" executed sum of 1 and 2.
N^2 + 1 + (N^4 + N^2) / 2 = (N^4 + 3N^2 + 2) / 2
= **(N^2 + 2) (N^2 + 1) / 2**

Related

unexpected result while evaluating the operators

I have below code and it gives an unexpected result. To my understanding, the result should be 6 but its 1. Can someone help me how to get it?
int j = 0;
int i1 = j*5+ ++j;
System.out.println("j =" + j);
System.out.println("i1 =" + i1);
The difference between getting 6 and getting 1 is whether you think j*5 will be evaluated first or ++j will be evaluated first. The rule in Java is that subexpressions are evaluated in the order they appear in the expression if the order is not forced by dependencies. Here, j*5 appears first in the expression, so it is evaluated first. That gives the 1 result.
You have something like the code below:
int j = 0;
int i1 = j*5+ ++j;
System.out.println("j =" + j);
System.out.println("i1 =" + i1);
You need to edit your code to this:
int j = 0;
int i1 = ++j*5 + j;
System.out.println("j =" + j);
System.out.println("i1 =" + i1);
Your final output for "i1 =" + i1) will be 6.
The issue is that in your first code sample you are not incrementing J before you multiply it by 5 so you're only increasing it by +1 because you don't actually increment j until you've multiplied 0 * 5. (0 * 5) + 1 = 1. What I did was simply increment j (in prefix form) so that it increments by 1, and now you're multiplying (1 * 5) + 1.

how many times will this loop execute

I was just wondering how many times a nested loop like this would run
int sum = 0;
for(int i = 0; i < total; i++) {
for(int j = i + 1; j < total; j++) {
for(int k = j; k < total; k++) {
sum++;
}
}
}
System.out.println(sum);
I can easily see the output of sum, but I would like to be able to mathematically calculate the total of sum with any number for total.
TL;DR
The loop will be executed for ((total ^ 3) - total) / 6 times and hence that will be the value of sum at the end of the loop.
int sum = 0;
for(int i = 0; i < total; i++) {
for(int j = i + 1; j < total; j++) {
for(int k = j; k < total; k++) {
sum++;
}
}
}
It is easy to see that the outer loop runs for a total times. The second loop is the trickier one
Let's try to work this out
i = 0, j runs from 1..total - 1
i = 1, j runs from 2..total - 1
i = 2, j runs from 3..total - 1
...
i = total - 2, j runs from total - 1 ..total - 1 (will only run once)
i = total - 1, inner loop does not execute as the loop termination condition is true.
The third loop is dependent on the second inner loop - k runs from j..total - 1
Let us take total as 6
j runs from 1..5 -> k runs for 5 times (j = 1) + 4 times(j = 2) + 3 times(j = 3)+ 2 times(j = 4) + 1 time(j = 4)
(Showing a minified version for others)
2..5 -> 4+3+2+1
3..5 3+2+1
4..5 2+1
5..5 1
Which is
1 + 2 + 3 + 4 + 5+
1 + 2 + 3 + 4 +
1 + 2 + 3 +
1 + 2 +
1
Generally,
1 + 2 + 3 + .. n +
1 + 2 + 3 +..n - 1+
1 + 2 + 3 +..n - 2+
1 + 2 + 3 +
1 + 2 +
1
This boils down to the sum
n * (n - 1)) / 2
For all values of n ranging from 1 to total
This can be verified with the below
int res = 0;
for (int i = 1; i <= total; i++) {
res += (i * (i - 1))/2;
}
res will be equal to your sum.
Mathematically, the above is
((total ^ 3) - total) / 6
Derivation:
References:
Sums of the First n Natural Numbers
Sum of the Squares of the First n Natural Numbers
The first iteration of the middle loop adds
total-1 + total-2 + ... + 1
to the sum.
The second iteration of the middle loop adds
total-2 + total - 3 + ... + 1
to the sum
The last iteration of the middle loop adds
1
to the sum.
If you sum all of these terms, you get
(total - 1) * 1 + (total - 2) * 2 + (total - 3) * 3 + ... + 2 * (total - 2) + 1 * (total - 1)
It's been a while since I studied math, so I don't remember if there's a simpler formula for this expression.
For example, if total is 10, you get:
9 * 1 + 8 * 2 + 7 * 3 + 6 * 4 + 5 * 5 + 4 * 6 + 3 * 7 + 2 * 8 + 1 * 9 =
9 + 16 + 21 + 24 + 25 + 24 + 21 + 16 + 9 =
165
It needs only a little bit knowledge of programming.Actually logic that is running behind is only computational kind of thing.
let's say:
total=10,sum=0
- when i is 0:
That time j is initialised with 1(i+1) and k as well. So k will lead us to execute the loop 9 times and and as j is incremented ,it will lead us to execute sum statement 8 times and 7 times and further 6 times till 1 time. (9+8+7+6+5+4+3+2+1=45 times.)
- when i is 1:
That time j is initialised with 2 and k as well.So sum statement is going to execute 8 times and then 7 times and then 6 times till 1.
(8+7+6+5+4+3+2+1=36 times).
- when i is 2:
Same thing happens repeatedly but starting with difference number ,so this time (7+6+5+4+3+2+1=28)
So this sequence continues until there is significance of occuring the condition with trueness.
This happens till i is 9.
So the final answer is 1+3+6+10+15+21+28+36+45=165.
The equation is like below
and the k is equal to total :
outermost loop runs 'total' number of times.
for each outer loop , middle loop runs 'total-i' times.
i.e total * total+total * (total-1)+total * (total-2)....total * 1
= total*(total+total-1+total-2...1)
= total*(1+2+3....total)
= total*(sum of first 'total' natural numbers)
= total*(total*(total+1)/2)
now the innermost loop also runs 'total-j' times for each middle loop
i.e
total*(total*(total+1)/2)*(total+(total-1)+(total-2)....+1)
= total*(total*(total+1)/2)*(1+2+3....+total)
= total*(total*(total+1)/2)* (sum of first 'total' natural numbers)
= total*(total*(total+1)/2) * (total*(total+1)/2)..
So finally you will get something close to
total * (total*(total+1)/2) * (total*(total+1)/2).
Sorry there's a correction as #andreas mentioned innermost and middle loops run only till total-i-1 times
in which case it will be the sum of first (total-1) no.s which should be (total-1)*total/2 so the final output should be
total * (total*(total-1)/2) * (total*(total-1)/2) .
As we know, the sum of an arithmetic progression is:
The inner-most loop will loop for
times, which is a function to j.
You sum it up and get a function to i, aka:
You sum it up again and get a function to total, aka:
For Mathematica users, the result is:
f[x_]:=Sum[Sum[x-j,{j,i+1,x-1}],{i,0,x-1}]
From here, we can see it more clearly, and the FINAL result is:
where x is total.
That function will loop (total/6)*(total*total - 1) times
The snippet bellow just verifies that
var total = 100
var sum = 0;
for(var i = 0; i < total; i++) {
for(var j = i + 1; j < total; j++) {
for(var k = j; k < total; k++) {
sum++;
}
}
}
function calc(n) {
return n*(n-1)*(n+1)/6
}
console.log("sum: "+sum)
console.log("calc: "+calc(total))
If we run this loop 100 times and generate a data set, then graph it, we get this:
Now, this graph is clearly a cubic. So we can do a solve using the cubic equation of ax^3+bx^2+cx+d.
Using 4 points, the values of them all are:
So the full equation is
y=x^3/6-x/6
y=x(x^2/6-1/6)
y=(x/6)(x^2-1)
Interactive Graph:
<iframe src="https://www.desmos.com/calculator/61whd83djd?embed" width="500px" height="500px" style="border: 1px solid #ccc" frameborder=0></iframe>
A simple loop like this:
for (i = a; i < b; i ++) {
....
}
runs b-a iterations (i takes the values: a, a+1, a+2... b-2, b-1) if a < b and 0 iterations otherwise. We will assume below that a < b always.
Its number of iterations can be compute using the simple maths formula:
Applying the formula to your code
We start with the innermost loop:
for(int k = j; k < t; k++) {
sum++;
}
Its number of iterations is:
Using the formula above, the value of U is (t-1)-j+1 which means:
U = t - j
Adding the middle loop
Adding the middle loop, the number of iterations becomes:
The terms of the second sum are t-(i+1), t-(i+2), ... t-(t-2), t-(t-1).
By solving the parentheses and putting them in the reverse order they can be written as:
1, 2, ... t-i-2, t-i-1.
Let p = t - j. The second sum now becomes:
It is the sum of the first t-i-1 natural numbers and its value is:
Adding the outer loop
Adding the outer loop the sum becomes:
On the last sum, the expression (t - i) starts with t (when i = 0), continues with t-1 (when i = 1) and it keeps decreasing until it reaches 1 (when i = t - 1). By replacing q = t - i, the last sum becomes:
The last expression subtracts the sum of the first n natural numbers from the sum of the first n square numbers. Its value is:
Now it's easy to simplify the expression:
The final answer
The number of iterations of the posted code is:

Magic square code loop

This is the code for a method which creates a magic square. n is the length of the square. It has to look like:
static int[][] magicSquare(int n) {
int[][] square=new int[n][n];
I don't understand this k=(k+1)%n; especially, why is it %n ?? Doesn´t that put k to 1 every loop again?
for (int i=0; i<n; i++){
in k=i;
for (int j=0; j<n; j++){
square[i][j]=k+1;
k=(k+1)%n;
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
The % in Java is used for modular division. Whenever the operator is applied the right-hand operand will be subtracted as many times as it can from the left-hand operand and what's left will be the output. You can easily check it by dividing the left-hand operand by the right-hand operand and take the leftover as an integer. In the case of a%b it will be like
a - (a/b)*b.
here are some examples:
10 % 4 = 2 // 2*4 = 8 + 2 = 10
10 % 5 = 0 // 2*5 = 10 + 0 = 10
0 % 4 = 0 // result here is 0 thus 0*4 = 0 + 0 = 0
// if you try to extract 4 from 0, you will not succeed and what's left will be returned (which was originally 0 and it's still 0)...
In your case:
k = (k + 1) % n;
is assuring that the value of k will never exceed 4, thus if it is dividable by 4 then it will be divided and the leftover will be written there. In the case when k is exactly 4 you will have the value of 0 written down into k but since you are always adding k + 1 it is writing the value of 1.
For beginners I do recommend to print the values you are interested in and observe how do the data migrate. Here I've added some printlns for you just to get the idea. Run the code and test it yourself. I do believe the things are going to be a bit cleaner.
public static void main(String[] args) {
int n = 4;
int[][] square = new int[n][n];
System.out.println("--------------");
for (int i = 0; i < n; i++) {
int k = i;
System.out.println("Filling magic cube line " + (i + 1) + ". The k variable will start from " + i + "."); // i initial value is 0 so we add 1 to it just to get the proper line number.
for (int j = 0; j < n; j++) {
System.out.println("Filling array index [" + i + "][" + j + "] = " + (k + 1)); // array indexes start from 0 aways and end at array.length - 1, so in case of n = 4, last index in array is 3.
square[i][j] = k + 1; // add 1 to k so the value will be normalized (no 0 entry and last entry should be equal to n).
k = (k + 1) % n; // reset k if it exceeds n value.
}
System.out.println("--------------");
}
Arrays.stream(square).forEach(innerArray -> {
Arrays.stream(innerArray).forEach(System.out::print);
System.out.println();
});
}
You could always play around and refactor the code as follows:
public static void main(String[] args) {
int n = 4;
int[][] square = new int[n][n];
System.out.println("--------------");
for (int i = 1; i <= n; i++) {
int k = i;
System.out.println("Filling magic cube line " + i + ". The k variable will start from " + i + ".");
for (int j = 0; j < n; j++) {
System.out.println("Filling array index [" + (i - 1) + "][" + (j - 1) + "] = " + k); // array indexes start from 0 aways and end at array.length - 1, so in case of n = 4, last index in array is 3. Subtract both i and j with 1 to get the proper array indexes.
square[i - 1][j - 1] = k;
k = (k + 1) % n; // reset k if it exceeds n value.
}
System.out.println("--------------");
}
Arrays.stream(square).forEach(innerArray -> {
Arrays.stream(innerArray).forEach(System.out::print);
System.out.println();
});
}
Remember that the array's indexing starts from 0 and ends at length - 1. In the case of 4, the first index is 0 and the last one is 3. Here is the diff of two implementations, try to see how does the indexes and values depends both on the control variables i and j.
https://www.diffchecker.com/x5lIWi4A
In the first case i and j both start from 0 and are growing till they it's values are both less than n, and in the second example they start from 1 and are growing till they are equal to n. I hope it's getting clearer now. Cheers

Why i += i + a[i++] + a[i++] + a[i++] results in 8?

I am totally lost why I get these results:
int i = 1;
int[] a = new int[6];
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
a[4] = 4;
a[5] = 5;
i += i + a[i++] + a[i++];
//i is 5
i = 1;
i += i + a[i++] + a[i++] + a[i++];
// i is 8
I (wrongly) thought that there are these options:
i = i(=1) + a[i++] + etc - meaning that i = 1 is cached and not
changed then. Expression evaluation order is exactly from left to
right, I guess (?!).
i is increased, which results (for first example) in i = i(=3) + a[1] + a[2] now i = 3 and written to leftmost i
value from rightmost a[THIS_VALUE] is substituted into leftmost i, and last increment is never made.
But actual results leave me with no clue...
i += i + a[i++] + a[i++];
adds the original value of i to the value of the expression i + a[i++] + a[i++] and assigns the result to i.
It's equivalent to
i = i + i + a[i++] + a[i++];
1 + 1 + a[1] + a[2] = 1 + 1 + 1 + 2 = 5
Then you assign 1 to i and calculate:
i += i + a[i++] + a[i++] + a[i++];
which is equivalent to
i = i + i + a[i++] + a[i++] + a[i++];
1 + 1 + a[1] + a[2] + a[3] = 1 + 1 + 1 + 2 + 3 = 8
The important thing to note is that each a[i++] increments i, but accesses the element of a at the index of the previous value of i (i.e. the value prior to the increment).
Therefore the first a[i++] returns a[1] (even though i is incremented to 2), the second a[i++] returns a[2] (even though i is incremented to 3) and the third a[i++] returns a[3] (even though i is incremented to 4).
This important to notice differences between i++ and ++i, when you use i++ it use i value to calculate the operation and then increment i, but when you are using ++i it increment i and the calculate the operation.
it also worth mentioning that i+=X is equal to i = i + X.
So
i += i + a[i++] + a[i++];
is equal to
i = i + i + a[i++] + a[i++]
for i = 1 it is
i = 1 + 1 + a[1] + a[2]
which with your initialisation it will be :
i = 1 + 1 + 1 + 2
and thats how you get i = 5. and same for next line.
Its quite easy acutally, your using post increment. Post increment increments the value after the expression was executed, versus pre which increments before the expression is executed. So i += i + a[i++] + a[i++] + a[i++];, is 1 += 1 + 1 + 2 + 3, the first access, uses 1, then increment, next access uses two then increment then last access uses three.

Running time of piece of Java code

I'm trying to figure out the running time of the following snippet of Java code:
static void counter(int N) {
int count = 0;
for (int i = 0; i < N; i += 1) {
for (int j = i + 1; j < N; j += 1) {
count += 1;
}
}
return count;
}
Just for clarification, the running time would be \Theta(N^2), right? The outer loop runs N times and the inner loop runs N-j times for each iteration of j. Putting this together gives \Theta(N^2).
Yes, Theta(n^2) is correct.
The inner loop runs (n-1) + (n-2) + ... + 1 + 0 iterations, which adds up to n * (n-1) / 2 = 0.5*n^2 - 0.5*n = Theta(n^2).
You are right.
Counting the number of iterations the inner loop runs for each iteration of the outer loop, you get :
N-1 + N-2 + N-3 + ... + 1 = ((N-1)*N)/2 = Theta(N^2)

Categories

Resources