I'm having a tough time with this for loop example - java

The method evenSquares takes a single int parameter, n, (for example, 10000), and then prints all of the (positive) even perfect squares less than n, each on a separate line.
Notice that evenSquares has a void return type, since all it does is print integers to the console. Be sure to use the println method to print each entry of your output.
Example: if n = 40, your code should print:
4
16
36
(Hint: your method should be built around a for loop with a test component that asks if the square of the control variable (say, k) is < n. Thus, the loop should terminate as soon as k*k equals or exceeds n.)
I'm given this
public void evenSquares(int n) {

public class Squares {
public static void main(String[] args) {
evenSquares(40);
}
public static void evenSquares(int n) {
for(int sq, k=2; (sq = k*k) <= n ; k += 2){
System.out.println(sq);
}
}
}

Related

Optimize the given Solution without changing the logic of the program. Also calculate the Time Complexity

This is a GFG practice problem hence compiler cannot be configured
Question
Given an array of positive integers. Your task is to find the leaders in the array.
Note: An element of array is leader if it is greater than or equal to all the elements to its right side. Also, the rightmost element is always a leader.
Input:
The first line of input contains an integer T denoting the number of test cases. The description of T test cases follows.
The first line of each test case contains a single integer N denoting the size of array.
The second line contains N space-separated integers A1, A2, ..., AN denoting the elements of the array.
Output:
Print all the leaders.
Constraints:
1 <= T <= 100
1 <= N <= 107
0 <= Ai <= 107
My Solution :
import java.util.*;
import java.io.*;
import java.lang.*;
public class Main
{
static BufferedReader z1 = new BufferedReader(new InputStreamReader(System.in));
public static void main (String[] args)throws Exception
{
int T=Integer.parseInt(z1.readLine());
while(T-- > 0)
{
int N=Integer.parseInt(z1.readLine());
solution ob = new solution();
int []a=new int[N];
a=ob.input(N,z1);
int x=0;
ob.leader(a,N,x);
}
}
}
class solution
{
static int[] input(int N, BufferedReader z1)throws Exception
{
int a[]=new int[N];
String s=z1.readLine();
String []str=s.split(" ");
/* for(int y=0;y<N;y++)
a[y]=Integer.parseInt(str[y]); */
toInts(str,a,0);
return a;
}
static void toInts(String[] strings, int[] ints, int start) {
if (start > strings.length - 1) {
return;
}
ints[start] = Integer.parseInt(strings[start]);
toInts(strings, ints, start+1);
}
static void leader(int []a,int N,int x)
{
int count = 0;
if(x==N-1)
System.out.println(a[x]);
else
{
count = compare(a,x,x+1,count,N);
/* for(int y=x+1;y<N;y++)
if(a[x]>=a[y])
count++; */
if(count==(N-x-1))
System.out.print(a[x]);
leader(a,N,x+1);
}
}
static int compare(int []a,int x,int y,int count,int N)
{
if(y==N)
return count;
else
{
if(a[x]>=a[y])
count ++;
return compare(a,x,y+1,count,N);
}
}
}
Error :
Runtime Error:
Runtime ErrorTime Limit Exceeded
Your program took more time than expected.Time Limit Exceeded
Expected Time Limit 3.00sec
A problem (and the likely cause for the long time it takes) is that your compare() method doesn't stop once it encounters a larger value and it is therefore obvious that the current element is not a leader. Instead it will always compare all values.
This makes the runtime of your code O(N^2) for an array of size N.
This problem can be solved in O(N).
Start on the right end of the array and print the last element as leader and set it as the current maximum. Then go left and check if the current element is greater or equal than the maximum. If yes print it as a leader and set is as the maximum. Continue until you reach the left end of the array.
You can also probably save some time by replacing your recursive toInts() method with a simple for-loop to convert the strings.

How can a recursive Java method be memoized?

So I've built this program to build different stair cases. Essentially the problem is: Given an integer N, how many different ways can you build the staircase. N is guaranteed to be larger than 3 and smaller than 200. Any previous step can not be larger than its following step otherwise it defeats the purpose of the staircase.
So given N = 3
You can build one staircase: 2 steps and then 1 step following that
Given N = 4
You can build one staircase: 3 steps and then 1 step following that
Given N = 5
You can build two staircases: 3 steps and then 2 steps OR 4 steps and then 1 step.
My method is below and it works, except its runtime is far too slow. So I was thinking of trying to make a memoization for the method, but to be honest I do not fully understand how to implement this. If I could get some help on how to do so that'd be great.
public static void main(String [] args)
{
System.out.println(answer(200));
}
public static int answer(int n) {
return bricks(1,n) -1;
}
public static int bricks(int height, int bricksLeft)
{
if(bricksLeft == 0)
{
return 1;
}
else if(bricksLeft < height)
{
return 0;
}
else
{
return bricks(height +1, bricksLeft - height) + bricks(height +1, bricksLeft);
}
}
Overview
So what you have here is a recursive solution. That works well for this type of problem. In this particular recursive solution, your recursive step will be called with the same arguments many times.
One really common optimization pattern for recursive solutions where the same calculation is being made many times is Dynamic Programming. The idea is that instead of doing the same calculation many times, we just cache each calculation the first time we do it. Then every following time, if we need to calculate the exact same value, we can just read the result from the cache.
Solution
With that in mind, this solution should work. It uses exactly the same logic as your original version, it just caches all results for the recursive step in a HashMap so that it never needs to calculate the same thing twice. It also uses a Staircase object to track pairs of (bricks, height). This is because we cannot insert pairs into a HashMap, we can only insert single objects.
Just change the variable bricks to whatever value you want to solve for.
public class Staircase {
private static HashMap<Staircase, Integer> cache;
public static void main(String[] args) {
cache = new HashMap<>();
int bricks = 6;
Staircase toBuild = new Staircase(1, bricks);
System.out.println(toBuild.waysToBuild() - 1);
}
public final int height;
public final int bricksLeft;
public Staircase(int height, int bricksLeft) {
this.height = height;
this.bricksLeft = bricksLeft;
}
public int waysToBuild() {
if (cache.containsKey(this)) {
return cache.get(this);
}
int toReturn;
if (bricksLeft == 0) {
toReturn = 1;
} else if (bricksLeft < height) {
toReturn = 0;
} else {
Staircase component1 = new Staircase(height + 1, bricksLeft - height);
Staircase component2 = new Staircase(height + 1, bricksLeft);
toReturn = component1.waysToBuild() + component2.waysToBuild();
}
cache.put(this, toReturn);
return toReturn;
}
#Override
public boolean equals(Object other) {
if (other instanceof Staircase) {
if (height != ((Staircase) other).height) {
return false;
}
if (bricksLeft != ((Staircase) other).bricksLeft) {
return false;
}
return true;
}
return false;
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + this.height;
hash = 73 * hash + this.bricksLeft;
return hash;
}
}
Analysis
I tested it out and the performance is much faster than your previous version. It computes values up to 200 instantly.
Your original function was O(2^n). That is because we make 2 recursive calls for each value from 1 to n, so the total number of calls is doubled for each time n is incremented.
The Dynamic Programming solution is O(n) since at most it will need to calculate the number of ways to make a staircase out of n bricks once for each value of n.
Additional Reading
Here is some more reading about Dynamic Programming: https://en.wikipedia.org/wiki/Dynamic_programming
Use a small class to hold the pairs (height, bricks), say:
private static class Stairs {
private int height;
private int bricks;
Stairs(int height, int bricks) {
this.height = height; this.bricks = bricks;
}
}
Then use a global HashMap<Stairs, Integer>, initialized in the main():
map = new HashMap<Stairs, Integer>();
In the bricks() function, check if the solution for a particular (height, bricks) pair is in the map. If yes, just return it from the map via a call to the get() method. Otherwise, do the computation:
Stairs stairsObj = new Stairs(height, bricks);
if(map.get(stairsObj) == null) {
// Put your compute code here
}
Before every return statement in the function, add two additional statements. Something like:
int result = <whatever you are returning right now>;
map.put(stairsObj, result);
return result;

Converting a number to a user chosen base

I want to make a thing that takes in a number, and a base system, such that it will convert the number to that number in a different base from base 2 to base 16.
E.g. stdin would be 67 and 2, meaning the user wants the program to change the number 67 into binary form. stdout would be 1000010.
So I made the following code to get it going at first. This program takes in a number and converts it to binary format.
public class ChangeofBase {
public static void main(String[] args) {
// read in the command-line argument
int n = Integer.parseInt(args[0]);
// set v to the largest power of two that is <= n
int v = 1;
while (v <= n/2) {
v *= 2;
}
// check for presence of powers of 2 in n, from largest to smallest
while (v > 0) {
// v is not present in n
if (n < v) {
System.out.print(0);
}
// v is present in n, so remove v from n
else {
System.out.print(1);
n -= v;
}
// next smallest power of 2
v /= 2;
}
System.out.println();
}
}
How can I modify the above code to perform the following function?
Take in a number n and a base k so that n will be converted to a number in base k
Once again, k has to be between 2 and 16. Base 2 and base 16. Binary and hexadecimal. Thank you!
Edit: I would like to do this without using built-in functions. Hardcoding
Edit 2: I am new to Java. So I would like to stick to the basic stuff such as defining variables, while loops and foor loops, if-else, and printing. and parsing command line args. I believe thats all we need for this program, though correct me if i'm wrong
You can use Integer.toString(int i, int radix).
Apart from the Java built in function, You can use simple division and modulus operations in Java to achieve that.
public class IntBaseConverter {
public static void main(String[] args) {
convert(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
}
public static void convert(int decimalValue, int base) {
String result = "";
while (decimalValue >= base) {
result = decimalValue % base + result;
decimalValue /= base;
}
result = decimalValue + result;
System.out.println(result);
}
}

Memoization with recursive method in java

I am working on a homework assignment, and I have completely exhausted myself. I'm new to programming, and this is my first programming class.
this is the problem:
Consider the following recursive function in Collatz.java, which is related to a famous unsolved problem in number theory, known as the Collatz problem or the 3n + 1 problem.
public static void collatz(int n) {
StdOut.print(n + " ");
if (n == 1) return;
if (n % 2 == 0) collatz(n / 2);
else collatz(3*n + 1);}
For example, a call to collatz(7) prints the sequence
7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
as a consequence of 17 recursive calls. Write a program that takes a command-line argument N and returns the value of n < N for which the number of recursive calls for collatz(n) is maximized. Hint: use memoization. The unsolved problem is that no one knows whether the function terminates for all positive values of n (mathematical induction is no help because one of the recursive calls is for a larger value of the argument).
I have tried several things: using a for loop, trying to count the number of executions with a variable incremented each time the method executed, and hours of drudgery.
Apparently, I'm supposed to use an array somehow with the memoization. However, I don't understand how I could use an array when an array's length must be specified upon initiation.
Am I doing something completely wrong? Am I misreading the question?
Here is my code so far. It reflects an attempt at trying to create an integer array:
public class Collatz2 {
public static int collatz2(int n)
{
StdOut.print(n + " ");
if (n==1) {return 1;}
else if (n==2) {return 1;}
else if (n%2==0) {return collatz2(n/2);}
else {return collatz2(3*n+1);}
}
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
StdOut.println(collatz2(N));
}
}
EDIT:
I wrote a separate program
public class Count {
public static void main(String[] args) {
int count = 0;
while (!StdIn.isEmpty()) {
int value = StdIn.readInt();
count++;
}
StdOut.println("count is " + count);
}
}
I then used piping: %java Collatz2 6 | java Count
and it worked just fine.
Since you are interested in the maximum sequence size and not necessarily the sequence itself, it is better to have collatz return the size of the sequence.
private static final Map<Integer,Integer> previousResults = new HashMap<>();
private static int collatz(int n) {
int result = 1;
if(previousResults.containsKey(n)) {
return previousResults.get(n);
} else {
if(n==1) result = 1;
else if(n%2==0) result += collatz(n/2);
else result += collatz(3*n + 1);
previousResults.put(n, result);
return result;
}
}
The memoization is implemented by storing sequence sizes for previous values of n in Map previousResults.
You can look for the maximum in the main function:
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
int maxn=0, maxSize=0;
for(int n=N; n>0; n--) {
int size = collatz(n);
if(size>maxSize) {
maxn = n;
maxSize = size;
}
}
System.out.println(maxn + " - " + maxSize);
}
The trick here is to write a recursive method where an argument is the value you want to "memoize". For instance, here is a version of a method which will return the number of steps needed to reach 1 (it supposes that n is greater than or equal to 1, of course):
public int countSteps(final int n)
{
return doCollatz(0, n);
}
public static int doCollatz(final int nrSteps, final int n)
{
if (n == 1)
return nrSteps;
final int next = n % 2 == 0 ? n / 2 : 3 * n + 1;
return doCollatz(nrSteps + 1, next);
}
If you were to record the different steps instead, you'd pass a List<Integer> as an argument and .add() to it as you went through, etc etc.

Printing fibonacci series in recursion

I am trying to print Fibonacci series using recursion and my code is not ending the recursion . Can you tell me if i missed something.I think the second recursion is going into infinite loop and i am not able to figure out why it is happening
class Main
{
public static void main (String[] args)
{
int k=7;
int x=0,y=1;
fib(x,y,k,0);
return;
}
public static void fib(int x,int y,int k,int cnt)
{
int z;
if(cnt>k)
return;
if(cnt<=k)
{
z=x+y;
x=y;
y=z;
System.out.println("value is"+z);
fib(x,y,k,cnt++);
}
}
}
You don't seem to understand the concept of Fibonacci Number. Please read the wikipedia article. Following is the code for this function.
public static int fib(int n)
{
if(n == 0 || n == 1)
return n;
return fib(n-1) + fib(n-2);
}
The issue is the post-increment in:
fib(x,y,k,cnt++);
This passes the original value of cnt to the recursive call, and then increments it.
If you print the value of cnt at the start of fib(), you'll see that it is always zero.
One easy fix is to change that call to
fib(x,y,k,cnt+1);
Also, your numbering of Fibonacci numbers is a bit odd (I'd say that the seventh number is 8 and your code thinks it's 34).
Finally, I may be worth noting that the second if is unnecessary.

Categories

Resources