Reducing the number of inner loop iterations in Java for efficiency - java

This is a mini-challenge from a Java textbook.
Following code can be made more efficient (by reducing the number of inner loop iterations, likely with a continue statement).
/*
Use nested loops to find factors of numbers
between 2 and 100.
In the program, the outer loop runs i from 2 through 100. The inner loop successively tests
all numbers from 2 up to i, printing those that evenly divide i.
*/
class FindFactors {
public static void main (String args[]) {
for (int i = 2; i <= 100; i++) {
System.out.print("Factors of " + i + ": ");
for (int j = 2; j < i; j++)
if ((i%j) == 0) System.out.print(j + " ");
System.out.println();
}
}
}
However I try to "simplify" just adds more steps. Any ideas?

In the inner loop test not all numbers up to i. It is enough if you only test up to half of i
for (int j = 2; j <= i/2; j++)

for (int j = 2; j < i; j++)
Without trying to spoil it, consider a natural number N for which you would calculate the factors. Perhaps you could reduce the amount of numbers you have to check?
Look up factoring integers for more information/different algorithms.

Set the length of the inner loop on the square of the index from the outer loop
Each number the max factor its his square

Related

What's the big O Notation for the two for loops

I am having a hard time analyzing this piece of code:
public int example(int[] arr){
int n = arr.length, total = 0 ;
for (int i=0; i < n; i++)
for (int j=0; j <= i; j++)
total += arr[j];
return total;
}
These two loops don't have curly braces. I could not analyze the time complexity of them.
I need help in counting the time of operation for both of them.
It is O(n2), since there are two layers of loops. The fact that there aren't curly braces does not matter.
The outer loop is executed O(n) times and the inner loop is executed first once, then twice, up until n times. This is an arithmetic sequence from 1 to n where the common difference is 1. Its sum is therefore
(1 + n) * (n) / 2
= (n^2 + n) / 2
= O(n^2)
That code could be rewritten with curly braces as follows:
for (int i=0; i < n; i++) {
for (int j=0; j <= i; j++) {
total += arr[j];
}
}
First loop is executed O(n) times.
Nested loop is executed O(n) times.
So overall O(n^2).

What's the Big O complexity of a ever decreasing range on a for loop?

I got 2 nested for loops, I calculate a new value for nrResults on every execution of the inner for loop (which will loop nnrResults - 2 times).
The time complexity should be of order O(n), since nrResults depends on the value of n.
But nrResults is being decreased on every loop of the outer for loop.(i.e. firstNext * j is growing with every iteration)
Is the time complexity of the inner for loop still O(n) even though nrResults will keep decreasing throughout execution?
for(int j = 1; j < B; j++) // General case
{
nrResults = n - (firstNext * j);
result = codedInput[0] + results[minI = minIndex(results, 0 + firstNext, nrResults + firstNext)];
for(int i = 1; i < nrResults; i++)
{
if( (i + firstNext) > minI)
results[i] = codedInput[i] + results[minI = minIndex(results, i + firstNext, nrResults + firstNext)];
else
results[i] = codedInput[i] + results[minI];
if(results[i] < result)
result = results[i];
}
}
In this case, you have one loop i:=0..n, and an inner loop j:=0..i-2. Is that so?
Complexity of inner loop will be O((n-1)/2), which is the average. Complexity of external for is O(n).
All you have to do is multiply O((n)*(n/2)), i.e. O(n²/2).
In case inner for iterations is different, you have to recalculate it.

analysis of algorithm run time

What would the big-O run time be? I'm mostly confused about the while loop run time. I know the run times for both for loops are O(n).
cin >> n >> min >> max;
for(int i = min; i < n; i++) {
for(int j = 1; j < max; j++) {
total = 1;
while(total < n) {
total = total *2;
}
}
}
The progression of target in the while loop is:
1 2 4 8 ... 2^P
You need log(2, n) steps -- i.e. log of n in base 2. That loop is O(log n).
First of all, it looks like you forgot to put braces. I'm your code, as it is, the whole loop is not inside the nested for loops. As it is, we have a pointless nested for loop that just sets total to 1, followed by an independent while loop. The complexity of the first is O((n - min) * max), and the second is O(log(n)). The total time complexity is the sum of these.
Probably what you really meant is this:
for(int i = min; i<n; i++) {
for(int j =1; j< max; j++) {
total = 1;
while(total < n) {
total = total *2;
}
}
}
Here, we have the whole loop inside the nested for loops. The time complexity is the multiple of what we calculated earlier, so O((n - min) * max * log(n)). If min and max are constants, then we can reduce to O(n log n)

Big-O of These Nested Loops

I'm pretty new to the Big-O field, so bear with me here. I have been searching about it as much as I could but I still need a lot of work to fully understand it.
I came across these nested for loops in a practicing exercises and there wasn't any solutions and they seem complicated. So, any help would be appreciated.
1)
int sum=0;
for(int i=0; i < n^2; i++) { // n+1
for(int j = n-1; j >= n-1-i; j–-) { // n(n+1)/2 ?
sum = i+j; // n(n+1)/2 ?
System.out.println(sum); // n(n+1)/2 ?
}
}
Big-O = ?
2)
int sum=0;
for(int i=1; i <= 2^n; i=i*2) { // log(n)
for(int j=0; j <= log(i); j++) { // log(n(n+1)/2) ?
sum = i+j; // log(n(n+1)/2) ?
System.out.println(sum); // log(n(n+1)/2) ?
}
}
Big-O = ?
3)
int sum = 0; int k = 23;
for(int i=k; i <= 2^(n−k); i=i*2) { // log(n)
for(int j=2^(i−k); j < 2^(i+k); j=j*2) { // log(log(n)) ?
sum = i+j; // log(log(n)) ?
System.out.println(sum); // log(log(n)) ?
}
}
Big-O = ?
4)
int sum=0;
for(int i=2n; i>=1; i=i/2) {
for(int j=i; j>=1; j=j/2) {
sum = i+j;
System.out.println(sum);
}
}
Big-O = ?
EDIT:
- Corrected #4. Sorry for the mess up.
- Base of the log is 2.
- The ^ here means "to the power", not xor.
There are plenty questions like "Big-O of nested loops" here on stackoverflow (and answers).
However, you will get an answer from me. But first there is a notation problem:
You tagged this question as java. In the code I see something like 2ⁿ or n². In java this means xor, but I think you meant Math.pow(2,n) instead, so for this answer I will treat it as a power operator.
int sum=0;
for(int i=0; i < n^2; i++) { // outer loop
for(int j = n-1; j >= n-1-i; j–-) { // inner loop
sum = i+j; // inner operations
System.out.println(sum);
}
}
The inner operations runs in O(1), so I just counting how often they are called.
The outer loop runs n² times.
for each i (from the outer loop) the inner loop runs i times.
In total you get 0+1+...+(n²-1)+n² = n²(n²+1)/2. This is in Θ(n⁴).
int sum=0;
for(int i=1; i <= 2^n; i=i*2) { // outer loop
for(int j=0; j <= log(i); j++) { // inner loop
sum = i+j; // inner operations
System.out.println(sum);
}
}
The outer loop runs n times, since 2⋅2⋅2⋅...⋅2 (n times) equals 2n.
The inner loop runs k times for each i=2k (1 ≤ k ≤ n), assuming the base of the logarithm is 2.
In total you get 1+2+3+...+n-1+n = n(n+1)/2. This is in Θ(n²).
int sum = 0; int k = 23;
for(int i=k; i <= 2^(n−k); i=i*2) { // outer loop
for(int j=2^(i−k); j < 2^(i+k); j=j*2) { // inner loop
sum = i+j; // inner operations
System.out.println(sum);
}
}
The outer loop runs m times with m minimal such that k⋅2m > 2n-k holds. This can be written as k⋅2k⋅2m > 2n. k has to be positiv (otherwise the outer loop will run forever). Assuming k is bounded by O(n) (canstants are also in O(n)), m is also bounded by O(n).
The inner loop runs always 2⋅k times, no matter what i or n is. This is in O(1) for a constant k and in O(n) for a k bounded by O(n).
In total you get O(n) for a constant k and O(n²) for a k in O(n).
int sum=0;
for(int i=2n; i>=1; i=i/2) { // outer loop
for(int j=i; j>=1; j=j/2) { // inner loop
sum = i+j; // inner operations
System.out.println(sum);
}
}
The outer loop runs log(n) times just like in case 2 (the other way around)
The inner loop runs j times for (basicly) each power of 2 between 1 and 2n.
Assuming n = 2k (means log(n) = k) you get in total
2k+1+2k+2k-1+...+22+21+20=2k+2-1=4n-1. So this in in O(n). This also holds for n not a power of 2.
Methodically finding a solution for your iterative algorithms using Sigma notation:
Using base 2 for the log below:

how to print a number triangle in java

I need to produce a triangle as shown:
1
22
333
4444
55555
and my code is:
int i, j;
for(i = 1; i <= 5; i++)
{
for(j = 1; j <= i; j++)  
{          
System.out.print(i); 
}      
System.out.print("\n");        
}
Producing a triangle the opposite way
1
22
333
4444
55555
What do i need to do to my code to make it face the right way?
You need 3 for loops:
Upper-level loop for the actual number to be repeated and printed
first inner level for printing the spaces
second inner level for to print the number repeatedly
at the end of the Upper-level loop print new line
Code:
public void printReversedTriangle(int num)
{
for(int i=0; i<=num; i++)
{
for(int j=num-i; j>0; j--)
{
System.out.print(" ");
}
for(int z=0; z<i; z++)
{
System.out.print(i);
}
System.out.println();
}
}
Output:
1
22
333
4444
55555
666666
I came across this problem in my AP CS class. I think you may be starting to learn how to program so heres what I'd do without giving you the answer.
Use a loop which removes the number of spaces each iteration. The first time through you would want to print four spaces then print 1 one time(probably done in a separate loop).
Next time through one less space, but print i one more time.
You need to print some spaces. There is a relation between the number of spaces you need and the number (i) you're printing. You can print X number of spaces using :
for (int k = 0; k < numSpaces; k++)
{
System.out.print(" ");
}
So in your code:
int i, j;
for(i = 1; i <= 5; i++)
{
// Determine number of spaces needed
// print spaces
for(j = 1; j <= i; j++)
{
System.out.print(i);
}
System.out.print("\n");
}
use this code ,
int i, j,z;
boolean repeat = false;
for (i = 1; i <= 5; i++) {
repeat = true;
for (j = 1; j <= i; j++) {
if(repeat){
z = i;
repeat = false;
while(z<5){
System.out.print(" ");
z++;
}
}
System.out.print(i);
}
{
System.out.print("\n");
}
}
You can use this:
int i, j;
int size = 5;
for (i = 1; i <= size; i++) {
if (i < size) System.out.printf("%"+(size-i)+"s", " ");
for (j = 1; j <= i; j++) {
System.out.print(i);
}
System.out.print("\n");
}
This line:
if (i < size) System.out.printf("%"+(size-i)+"s", " ");
Is going to print the left spaces.
It uses the old printf with a fixed sized string like 5 characters: %5s
Try it here: http://ideone.com/jAQk67
i'm having trouble sometimes as well when it's about formatting on console...
...i usually extract that problem into a separate method...
all about how to create the numbers and spacing has been posted already, so this might be overkill ^^
/**
* creates a String of the inputted number with leading spaces
* #param number the number to be formatted
* #param length the length of the returned string
* #return a String of the number with the size length
*/
static String formatNumber(int number, int length){
String numberFormatted = ""+number; //start with the number
do{
numberFormatted = " "+numberFormatted; //add spaces in front of
}while(numberFormatted.length()<length); //until it reaches desired length
return formattedNumber;
}
that example can be easily modified to be used even for Strings or whatever ^^
Use three loops and it will produce your required output:
for (int i=1;i<6 ;i++ )
{
for(int j=5;j>i;j--)
{
System.out.print(" ");
}
for(int k=0;k<i;k++)
{
System.out.print(i);
}
System.out.print("\n");
}
Your code does not produce the opposite, because the opposite would mean that you have spaces but on the right side. The right side of your output is simply empty, making you think you have the opposite. You need to include spaces in order to form the shape you want.
Try this:
public class Test{
public static void main (String [] args){
for(int line = 1; line <= 5; line++){
//i decreases with every loop since number of spaces
//is decreasing
for(int i =-1*line +5; i>=1; i--){
System.out.print(" ");
}
//j increases with every loop since number of numbers
//is decreasing
for(int j = 1; j <= line; j++){
System.out.print(line);
}
//End of loop, start a new line
System.out.println();
}
}
}
You approached the problem correctly, by starting with the number of lines. Next you have to make a relation between the number of lines (the first for loop) and the for loops inside. When you want to do that remember this formula:
Rate of change*line + X = number of elements on line
You calculate rate of change by seeing how the number of elements change after each line. For example on the first line you have 4 spaces, on the second line you have 3 spaces. You do 3 - 4 = -1, in other words with each line you move to, the number of spaces is decreasing by 1. Now pick a line, let's say second line. By using the formula you will have
-1(rate of change) * 2(line) + X = 3(how many spaces you have on the line you picked).
You get X = 5, and there you go you have your formula which you can use in your code as you can see on line 4 in the for loop.
for(int i = -1 * line +5; i >= 1; i--)
You do the same for the amount of numbers on each line, but since rate of change is 1 i.e with every line the amount of numbers is increasing by 1, X will be 0 since the number of elements is equal to the line number.
for(int j = 1; j <= line; j++){

Categories

Resources