My prof does not like the use of modulo since it's not efficient enough, but I'm not sure how else I can get the same answer using a logic operator or something. Can someone help me out with how I can do this?
j = (j + 1) % a.length;
This should do the trick.
int k = a.length;
int d = (j+1)/k;
j = (j+1) - d*k
The only way I can see of doing this without a modulo is still not great:
j = (++j < a.length)? j : (j - a.length);
Alternately, for more readability:
j++;
j = (j < a.length)? j : (j - a.length);
or
j++;
if (j >= a.length) {
j -= a.length;
}
Also, I'm not entirely sure about how Java does with loop prediction, but at least in C, the following would be slightly better for speed, if less readable, since the general assumption is that the argument to the if statement will be true, and j < a.length more often than not (Unless a.length <= 2, which seems unlikely.)
j++;
if(j < a.length) {
}
else {
j -= a.length;
}
If the initial value of j is outside the range 0 to a.length (inclusive-exclusive), then the only solutions either use a modulus or division, which, being the same operation, are the same speed, or a loop of subtraction, which will essentially accomplish the same thing as modulus on a very old processor, which is slower than the built in operation for modulus on any current processor I know about.
You could do this:
j = j + 1;
if (j >= a.length) {
j = j - a.length; // assumes j was less than length before increment
}
#ajp suggests another solution that actually would work ok.
j = j + 1;
if (j >= a.length) { // assumes j was less than length before increment
j = 0;
}
If I was writing the code, id write it this way, just in case. It has very little additional overhead and removes the "assumes"
j = j + 1;
while (j >= a.length) {
j = j - a.length;
}
Of course, the % would be a good way to do it too. Unless one is your professor.
This could be faster or slower than a divide/modulo depending on the cost of a jump (and any effect that has on the instruction pipeline/lookahead) and the efficiency of the integer division instructions.
Old processors would likely do better with the jump. More modern ones with the divide.
Think of what you are doing here. You are essentially saying:
if j + 1 is smaller than a.length, set j to j + 1
otherwise, we set j to a value smaller than a.length
This pseudocode should give you a very clear hint to the solution.
Related
I'm writing Shellsort in Java and found that adding a criteria in a for loop significantly improves the speed. Can someone explain why?
This is the fast code, 80ms for 10K Doubles.
public static void sort(Comparable[] a) {
if (a.length <= 1) {
return;
}
// Using 3K+1 starting from < N/3 as in the book
int magic = 1;
while (magic < a.length / 3) {
magic = 3 * magic + 1;
}
while (magic >= 1) {
for (int i = magic; i < a.length; i += 1) {
if (less(a[i - magic], a[i])) {
// Already in good order
continue;
}
for (int j = i; j >= magic && less(a[j], a[j - magic]); j -= magic) {
// if (less(a[j], a[j - magic])) {
exch(a, j, j - magic);
// }
}
/*
for (int j = 0; j < i; j += 1) {
if (less(a[i], a[j])) {
// j is the right place
// Use a series of exchanges to avoid creating new arrays
for (int k = i; k > j; k -= 1) {
exch(a, k-1, k);
}
break;
}
}
*/
}
magic /= 3;
}
}
The slow version (I'll just put the inner for loop here) which takes around 43,000ms
for (int j = i; j >= magic; j -= magic) {
if (less(a[j], a[j - magic])) {
exch(a, j, j - magic);
}
}
Please note that the less function simply check whether a[j] is smaller than a[j-magic].
From what I understand, in the fast code, we still check the less criteria for each loop, and if it doesn't satisfy we don't go inside the loop. In the slow version, we do go inside each loop and even less is not satisfied we don't do the exchange. What I don't understand is why the fast code is SO much faster? And is it the same for C++? (I could test the C++ part by myself)
Let's consider the slow version of the loop:
for (int j = i; j >= magic; j -= magic) {
if (less(a[j], a[j - magic])) {
exch(a, j, j - magic);
}
}
In this loop, we call less for each value of j, and for the values for which less return true, we call exch. This happens until j >= magic.
Now, let's look at the faster version:
for (int j = i; j >= magic && less(a[j], a[j - magic]); j -= magic) {
exch(a, j, j - magic);
}
In this version, we also call less for each value of j, but for the first value of j it returns false, the execution exits the loop. So, in this condition after the loop exits, it is not necessary that j < magic. As a result, many calls to exch and less are saved here, which results in optimization.
This will be the same for every language.
int n = 3;
int x = n;
int y = 0;
for(int i = n; i > 0; i--)
for(int j = 0; j <=n; j++)
if(j > n)
for(int k = 1; k <=n; k++)
System.out.println("x is " +x--);
else
System.out.print("y is " +y++);
under the if statement if(j > n) why is that the for loop is not performed?
i can't really understand why, because our instructor let us analyze the running time and i can't really understand why that for loop is not performed during the execution. please help me..
for(int j = 0; j <=n; j++)
if(j > n)
What you are saying in the for loop is: Execute this code while j is less or equal to n.
Then on the if you say: If j is greater than n.
j will never be greater than n as the for loop limits j falue to be less or equal than n.
That's pretty basic and you should read more on how for works.
Also, avoid not using {}, it's very dangerous. Prefer to always do:
for(int j = 0; j <=n; j++) {
if(j > n) {
....
}
}
count++;
count++;
count++;
for (int i = 0; i < n; i++)
{
for(int j = 0; j < i*i; j++)
{
for (int k = 0; k < j; k++)
{
count++;
sum++;
}
}
}
count++;
return count;
}
Trying to get the Big O of this coding. Struggling to understand how the loops interact. When I run it, I get n = 25 count = 898960. I've tried O(n)^5+9 all the way to O(n)^5/n
All other examples of this problem don't deal with I is used in the second loop (I*I) and j is used in the third loop
Almost always the best way to compute complexities of kinda loops should be done by making use of sigma notation.
P.S. I don't write necessary +1s in the formulas since it is not important for Big-O notation and doesn't affect max power which is 5.
It looks like it is O(n^5).
for (int i = 0; i < n; i++) // 0 to n -> O(n)
for(int j = 0; j < i*i; j++) // 0 to n * n -> O(n^2) repeated n times -> O(n^3)
for (int k = 0; k < j; k++) // 0 to n * n -> O (n^2) repeated O(n^3) times -> O(n^5)
In the best case scenario, three nested loops would give you O(n^3), but as you have the second loop repeat (n^2) times, that will square its complexity and of the third loop as well. So in a simple mathematical notation that will be: (n) * (n * n) * (n * n) = n^5.
I'm trying to solve a puzzle on hackerrank (the Sherlock and Queries puzzle - https://www.hackerrank.com/challenges/sherlock-and-queries). After working on it for a while, I started digging around on the internet for some help. I found one post here https://codereview.stackexchange.com/questions/58095/sherlock-and-queries-challenge?newreg=0bf47176275d428dbdfa0c6a4bc86f07 that confused me. It looks as if he changes this
for (int j = 0; j < N; ++j) {
if (j % B[i] == 0)
...
}
into this
for (int j = B[i] - 1; j < N; j += B[i]) {
...
}
Can someone please explain how these two are equivalent?
Assuming B[i] is an integer >= 2, the two snippets would be equivalent only if the second would be :
for (int j = 0; j < N; j += B[i]) {
}
Thus j would iterate over all the values that are divisible by B[i], which are exactly the values of j for which the condition in the first loop is true.
If j is initialized to B[i]-1, j%B[i] is never 0, so the second loop is not equivalent to the first loop.
The two are not equal.
The right equivalent for the first form that comes close to the second form would be:
for (int j = 0; j < N; j += B[i]) {
...
}
The first form lets j go from 0 to N and chooses only to act when j is dividable by B[i] (without a rest value). The second form gets the same result, by letting j go to B[i] * 0, B[i] * 1, B[i] * 2.....N. If you think about it, only multiples of B[i] are dividable by B[i] (without a rest value).
I implemented the Sieve of Eratosthenes in Java, from pseudocode:
public static void sieveofEratosthenes(int n) {
boolean numArray[];
numArray = new boolean[n];
for(int i = 0; i < n; i++)
numArray[i] = true;
int a = 0;
for(int i = 2; i < Math.sqrt((double)n); i++) {
if(numArray[i]) {
for(int j = (int)Math.pow(i, 2); j < n; a++) {
numArray[j] = false;
j += (a * i);
}
}
}
for(int i = 2; i < n; i++) {
if(numArray[i])
System.out.println(i);
}
}
The output it gives me, when i is 15:
2
3
5
7
8
11
12
13
14
Why are some of these values incorrect? I believe my error is in how I define and use the bool array. Thanks!
for(int j = (int)Math.pow(i, 2); j < n; a++) {
numArray[j] = false;
j += (a * i);
}
should read
for(int j = (int)Math.pow(i, 2); j < n; j+=i) {
numArray[j] = false;
}
How SoE works is that it takes each number and "deletes" all numbers following it that are divisible by it. So basically each number x + k*x where k > 0. This can be done by simply adding x to the initial x^2 and then adding iteratively x to it. Here:
for(int j = (int)Math.pow(i, 2); j < n; a++) {
numArray[j] = false;
j += (a * i);
}
You are not adding x but a*x, so you will skip some numbers as a is being incremented (so you will remove 4,6,10,16 etc, see the pattern? it adds 2,4,6 etc to the initial value) so you should stick with:
for(int j = (int)Math.pow(i, 2); j < n; j+=i) {
numArray[j] = false;
}
The problem is at line
j += (a * i);
In loop, this statement gradually multiplies the j by a*i and add it with j.So replace above line with,
j = (a * i);
It will work.
And yes,initialize
a=2
because we don't want numarray[0] or numarray[1] to initialize or use.
Do comment if any query. Thanks
This doesn't directly address your question, but since it's already been answered, I don't see any point in repeating it. Looking at your code, though, I suggest using integer multiplication instead of Math.pow and Math.sqrt to get slightly better performance such as:
for(int i = 2; i*i < n; i++) {
if(numArray[i]) {
for(int j = i*i; j < n; j += i) {
numArray[j] = false;
}
}
}
Admittedly these calls will only be made once per iteration of the outer loop, so the improvement may not be very dramatic. But, calling Math.pow and Math.sqrt are likely to be much more compute intensive than a single integer multiplication. Also, if Java performs sufficiently sophisticated optimization, i*i may only get computed once and used in both places saving even more compute cycles. There's also no risk of integer overrunning in this case since i*i is bounded above by the integer n.