Jump Game Correction - java

I'm not sure how to improve my solution for the jump game question (https://leetcode.com/problems/jump-game/description/) .It seems logically correct but I encounter a java.lang.Stackoverflow error for large inputs like [nums=[1,1,1,1,1,1,1,........]]
I know that I'm overflowing due to too many recursive calls , how can i optimize it ?
class Solution {
public boolean canJump(int[] nums) {
int []f = new int[1];
f[0] = 0;
return help(nums,0,f);
}
public static boolean help(int[]nums, int c, int[] f) {
if(c==nums.length-1) {
f[0] =1;
return true;
}
if(f[0]==1) return true;
int val = nums[c];
for(int i = 1; i <= val; i++) {
if(f[0]==1) return true;
return help(nums,(c + i), f);
}
return false;
}
}

This can be solved in T:O(N) with greedy algorithm:
class Solution {
public int jump(int[] nums) {
int res=0, l=0, r=0;
while(r<(nums.length-1)){
int farthest=0;
for (int i=l;i<r+1;i++){
farthest=Integer.max(farthest,i+nums[i]);
}
l=r+1;
r=farthest;
res++;
}
return res;
}
}
Explanation
nums = [2,3,1,1,4]
you jump 2 steps. you get the index 2.so you are jumping elements [3,1]. Nov you loop through [3,1] and check which one will take you to the further. In this case it is 3. Then update the variables. Increase res=1
From element 3 which is index-1. you jump 3 steps, jumping [1,1,4]. Now loop through [1,1,4] find the farthest. which is 4. increase res=2. Since out of while loop, return res=2.
It seems to have two nested loops, but if you look carefully, total iteration is N.

Related

find if given pack of coins can make a given value - coin row problem

given array of coins (int) and an int n the function need to return true if there is atleast one solution to the coin-change problem.
meaning: for array of ints> 0: [c(0) ,c(1) ,c(2) ,c(3) ,...... ,c(k)]. check if there is a solution for
the eqauation: a(0)*c(0)+ a(1)*c(1)+.....+ a(k)*c(k)= n. //n is the money we need to change
given c(0),c(1),....,c(n) >0 and a(0),a(1),....,a(n) =>0 both integers.
so I managed to make this code: the problem is that its algorithmic efficiency sucks, and this should be running on high values, and big coins array, so I need a code that is able to do this quicker.
public static boolean change(int[] coins, int n) {
boolean ans = false;
//loop running in recursion till founds ans/ passing limit
for (int i = 0; i < coins.length & (!ans); i = i + 1) {
if (n % coins[i] == 0) {
return true;
}
if (n >= coins[i]) {
ans = change(coins, n - coins[i]);
}
}
return ans;
}//O(n*k^n) solution for false ans , very bad :(
for example: for coins = {2,4,8} and n= 4111; I should get false, but the program unable to run this.
btw I would prefer this function to use recursion, but any solution/ guidnes is good :)
this is an other try doing this better but still not running as wanted.
//trying to use binary search and using divisions instead of minus
public static int iscashable(int[] coins, int n, int min, int max)
{
int check=(max+min)/2;
if(check == coins.length-1 | check == 0)
return check;
if(n/coins[check] > n% coins[check])
{
return (iscashable(coins,n,check,max));
}
else
{
return check;
}
}
public static int canchange(int[] coins, int n, int count)
{
int x=0;
int check= iscashable(coins,n,0,coins.length-count);
if(n%coins[check]==0)
{
return 0;
}
if(check==0)
{
return n;
}
if(n/coins[check] > n% coins[check])
{
x= (n/coins[check]) - (n% coins[check]);
int k= n-(coins[check]*x);
return canchange(coins, k, count+1);
}
else
{
return canchange(coins,n-coins[check],count+1);
}
}
the problem is both about runtime and number of recursion calls (with big number given, every recursion layer is coins.length^(num of layers));
I really thank you for your help!

Find if a number is in an array, and if so, how many times does it appear

The problem is there is an array of 10000 that is already filled for me. The range of numbers that will fill the array will be between 0 and 2500. The array is unsorted. My goal is to find the existence of 1320 through one linear search, and the second linear search will check how many times the number 1320 appears. The array is a random array.
I have tried setting up a linear search that will check whether the number in the array exists. I have also tried to set up the linear search that will check how many times an array exists. Neither worked, this is my first time working with arrays so I am not sure if I am even doing them correctly
public static void main(String[] args) {
// Finish adding Code
boolean DoesItExist;
int iHowMany;
final int SIZE = 10000, ENTRY = 1320;
int[] NumArray = new int[SIZE];
OwenHeading.getHeader("Assignment 9: Arrays.");
fillTheArray(NumArray, SIZE);
System.out.println("DONE");
}
public static void fillTheArray(int[] iTempArray, int SIZE) {
final int RANGE = 2500;
Random rand = new Random();
for (int index = 0; index <= SIZE - 1; index++)
iTempArray[index] = rand.nextInt(RANGE);
}
public static boolean linearSearchOne(int[] iTempArray, int SIZE, int ENTRY) {
boolean TempDoesItExist;
return TempDoesItExist;
}
public static int linearSearchTwo(int[] iTempArray, int SIZE, int ENTRY) {
int HowManyExist;
return HowManyExist;
}
public static void programOutput(boolean TempDoesItExist, int TempHowMany) {
if (TempDoesItExist)
System.out.println("does");
// Cool, you found the number 1320
else
System.out.println("does not");
// Dang, you didn't find the number 1320
}
}
I am not asking for the exact answer, just some help that will get me going into the right direction. I feel like I would be able to do this project easier if I started from scratch, but my teacher wants us to use his starter project.
Initialize your boolean and counter
Bool doesItExist = false;
Int iHowManyTimes = 0;
You can check for values in arrays in java in a linear fashion like this:
for (int number : NumArray) {
if (anItemInArray == myValue) {
doesItExist = true;
return;
}
}
afterwards do it all over again and increment your counter
for (int number : NumArray) {
if (number == ENTRY) {
iHowMany += 1;
}
}
Edit: Return statement added to first loop, as there is no reason to continue after the value is found
you can modify two methods of linear search you have in this way and that is going to work :
just declare a counter and increment it each time you find your ENTRY number.
public static boolean linearSearchOne(int[] iTempArray, int SIZE, int ENTRY) {
for (int i = 0; i < SIZE; i++) {
if (iTempArray[i] == ENTRY) {
return true;
}
}
return false
}
public static int linearSearchTwo(int[] iTempArray, int SIZE, int ENTRY) {
int HowManyExist;
for (int i = 0; i < SIZE; i++) {
if (iTempArray[i] == ENTRY) {
HowManyExist ++;
}
}
return HowManyExist;
}
It looks like you didn't call the linear search methods. For a linear search you can just do something like the following:
found=false;
howManyCounter=0;
for (int x=0, x<array.length; x++){
if (array[x]==numberYouWant){
found=true;
howManyCounter++;
}
}

Prime Number code

Let me start off by saying that I know there are many questions about prime numbers, this is more about my code and, specifically, the Boolean statements.
public class SumPrime
{
public static void main(String[] args) {
int top = inputInt("enter the number please");
int sum;
if (top > 2) {
sum = 2;
} else {
sum = 0;
}
int i;
int l;
for(l=3; l<top; l+=2){
boolean k = test(l);
String r;
if(k = true){
sum=sum+l;
output(l);
}else {
sum=sum;
}
}
System.out.println("The sum is " + sum);
}
static boolean test(int v) {
if (v%2==0)
return false;
for(int i=3; i<v; i+=2) {
if(v%i==0)
return false;
}
return true;
}
I am trying to code a program that will give me the sum of primes below an input value.
Below the above code, I have Input/Output statements, so that is not a problem. This code seems, to me at least, that it should work without a problem. I am relatively new to java, and very new to boolean variables and statements, so there could easily be a problem in that. (I searched for an answer, found nothing)
The test subprogram is supposed to check to see if a number is prime, and return true if it is, false if it is not. It seems to be returning true for every value, even for numbers that are not prime. The program returns a sum of 26, rather than 17 If i input 10 as the upper limit. It seems to be including every odd number even though it is supposed to check for primes.
I cannot figure out why this code does not work. Like I said, I think the error has something to do with the boolean method.
if you test 9 with this i < 9 is tested.
when i = 9 the for loop aborts and it returns true
static boolean test(int v) {
if (v%2==0)
return false;
for(int i=3; i<v; i+=2) {
if(v%i==0)
return false;
}
return true;
}
Edit:
also you should never test for primes above half the target number and the ideal maximum is sqrt(x) + 1
Your problem has nothing to do with your boolean method. Your condition is bad. You are performing an assignment in the conditional rather than actually testing equality. As a result, it always evaluates to true, and you end up adding where you shouldn't.
Do this instead:
if (k) {
sum += l;
}
Incidentally, sum = sum doesn't so anything and should be removed too.

Prime Tester for speed

I was given a homework assignment in Java to create classes that find Prime number and etc (you will see in code better).
My code:
class Primes {
public static boolean IsPrime(long num) {
if (num%2==0){
return false;
}
for (int i=3; i*i<=num;i+=2) {
if (num%i==0) {
return false;
}
}
return true;
} // End boolen IsPrime
public static int[] primes(int min, int max){
int counter=0;
int arcount=0;
for (int i=min;i<max;i++){
if (IsPrime(i)){
counter++;
}
}
int [] arr= new int[counter];
for (int i=min;i<max;i++){
if (IsPrime(i)){
arr[arcount]=i;
arcount++;
}
}
return arr;
} // End Primes
public static String tostring (int [] arr){
String ans="";
for (int i=0; i<arr.length;i++){
ans= ans+arr[i]+ " ";
}
return ans;
}
public static int closestPrime(long num){
long e = 0 , d = 0 , f = num;
for (int i = 2; i <= num + 1 ; i++){
if ((num + 1) % i == 0){
if ((num + 1) % i == 0 && (num + 1) == i){
d = num + 1;
break;
}
num++;
i = 1;
}
}
num = f;
for (int i = 2; i < num; i++){
if ((num - 1) % i == 0){
if ((num - 1) % i == 0 && (num - 1) == i){
e = num - 1;
break;
}
num--;
i = 1;
}
}
num = f;
if (d - num < num - e) System.out.println("Closest Prime: "+d);
else System.out.println("Closest Prime: "+e);
return (int) num;
} // End closestPrime
}//end class
The goal of my code is to be faster (and correct). I'm having difficulties achieving this. Suggestions?
**New code:
class Primes {
public static boolean IsPrime(int num) {
if (num==1){
return false;
}
for (int i=2; i<Math.sqrt(num);i++) {
if (num%i==0) {
return false;
}
}
return true;
}
// End boolen IsPrime
public static int[] primes(int min, int max){
int size=0;
int [] arrtemp= new int[max-min];
for (int i=min;i<max;i++){
if (IsPrime(i)){
arrtemp[size]=i;
size++;
}
}
int [] arr= new int[size];
for (int i=0;i<size;i++){
arr[i]=arrtemp[i];
}
return arr;
}
public static String tostring (int [] arr){
String ans="";
for (int i=0; i<arr.length;i++){
ans= ans+arr[i]+ " ";
}
return ans;
}
public static int closestPrime(int num) {
int count=1;
for (int i=num;;i++){
int plus=num+count, minus=num-count;
if (IsPrime(minus)){
return minus;
}
if (IsPrime(plus)) {
return plus;
}
count=count+1;
}
} // End closestPrime
}//end class
I did try to make it a bit better. what do you think, it can be improved more? (the speed test is still high...)
In your primes function you:
Check if the current number is divisible by two
Check to see if it's prime
Create an array to put your output in.
Check every number in the range again for primality before putting it in your array.
The problem is in the last step. By double-checking whether each number is prime, you're duplicating your most expensive operations.
You could use a dynamic data structure and add prime numbers to it as you find them. That way you only need to check once.
Alternatively, you could create a boolean array which is the size of your input range. Then as you find primes, set the corresponding array value to true.
UPDATE:
There are still a number of improvements you can make, but some will require more work than others to implement. Look at the specifics of your test and see what fits your needs.
Low-hanging fruit:
Use an ArrayList to collect primes as you find them in primes, as opposed to looping over the values twice.
In closestPrime, you're checking every single value on either side of num: half of these are even, thus not prime. You could adapt your code to check only odd numbers for primality.
Trickier to implement:
Try a more advanced algorithm for IsPrime: check out the Sieve of Eratosthenes
Above all, you should spend some time figuring out exactly where the bottlenecks are in your code. Oftentimes performance problems are caused by code we thought was perfectly fine. You might consider looking into the code-profiling options available in your development environment.
You make quite a few calls to isPrime(), each of which is very expensive. Your first step should be to minimize the number of times you do that, since the result doesn't change for any given number, there's no point calling more than once. You can do this with memoization by storing the values once they're computed:
ArrayList<Integer> memoList = new ArrayList<Integer>();
for(int i = 0; i < max; i++) {
if(isPrime(i)) {
memoList.add(i);
}
}
Now memoList holds all the primes you need, up to max, and you can loop over them rapidly without needing to recompute them every time.
Secondly, you can improve your isPrime() method. Your solution loops over every odd number from 3 to sqrt(n), but why not just loop over the primes, now that we know them?
public static boolean IsPrime(long num) {
for(int p : memoList) {
if(num % p == 0) {
return false;
}
}
return true;
}
These changes should dramatically improve how quickly your code runs, but there has been a lot of research into even more efficient ways of calculating primes. The Wikipedia page on Prime Numbers has some very good information on further tactics (prime sieves, in particular) you can experiment with.
Remember that as this is homework you should be sure to cite this page when you turn it in. You're welcome to use and expand upon this code, but not citing this question and any other resources you use is plagiarism.
I see a couple problems with your answer. First, 2 is a prime number. Your first conditional in IsPrime breaks this. Second, in your primes method, you are cycling through all number from min to max. You can safely ignore all negative numbers and all even numbers (as you do in IsPrime). It would make more sense to combine these two methods and save all the extra cycles.

Project Euler (P14): recursion problems

Hi I'm doing the Collatz sequence problem in project Euler (problem 14). My code works with numbers below 100000 but with numbers bigger I get stack over-flow error.
Is there a way I can re-factor the code to use tail recursion, or prevent the stack overflow. The code is below:
import java.util.*;
public class v4
{
// use a HashMap to store computed number, and chain size
static HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
public static void main(String[] args)
{
hm.put(1, 1);
final int CEILING_MAX=Integer.parseInt(args[0]);
int len=1;
int max_count=1;
int max_seed=1;
for(int i=2; i<CEILING_MAX; i++)
{
len = seqCount(i);
if(len > max_count)
{
max_count = len;
max_seed = i;
}
}
System.out.println(max_seed+"\t"+max_count);
}
// find the size of the hailstone sequence for N
public static int seqCount(int n)
{
if(hm.get(n) != null)
{
return hm.get(n);
}
if(n ==1)
{
return 1;
}
else
{
int length = 1 + seqCount(nextSeq(n));
hm.put(n, length);
return length;
}
}
// Find the next element in the sequence
public static int nextSeq(int n)
{
if(n%2 == 0)
{
return n/2;
}
else
{
return n*3+1;
}
}
}
Your problem is not with the size of the stack (you're already memoizing the values), but with
the size of some of the numbers in the sequences, and
the upper limits of a 32-bit integer.
Hint:
public static int seqCount(int n)
{
if(hm.get(n) != null) {
return hm.get(n);
}
if (n < 1) {
// this should never happen, right? ;)
} ...
...
That should hopefully be enough :)
P.S. you'll run into a need for BigNums in a lot of project euler problems...
If you change from integer to long it will give you enough room to solve the problem.
Here was the code that I used to answer this one:
for(int i=1;i<=1000000;i+=2)
{
steps=1;
int n=i;
long current=i;
while(current!=1)
{
if(current%2==0)
{
current=current/2;
}else{
current=(current*3)+1;
}
steps++;
}
if(steps>best)
{
best=steps;
answer=n;
}
}
Brute forcing it, takes about 9 seconds to run
Side note (as it seems that you don't actually need tail call optimization for this problem): tail call optimization is not available in Java, and as far as I have heard, it is not even supported by the JVM bytecode. This means that any deep recursion is not possible, and you have to refactor it to use some other loop construct.
If you are counting the size of the Collatz sequence for numbers upto 1,000,000
you should re-consider using Integer type. I suggest using BigInteger or possible a long.
This should alleviate the problems encountered, but be warned you may still run out of heap-space depending on your JVM.
I think you need these 2 hints :
Don't use Integer because at some starting number, the sequence will fly into some numbers greater than Integer.Max_VALUE which is 2147483647. Use Long instead.
Try not to use recursion to solve this problem, even with memoization. As i mentioned earlier some numbers will fly high and produce a great deal of stacks which will lead into stack overflow. Try using "regular" iteration like do-while or for. Of course you can still use some ingredient like memoization in "regular" loop.
Oh i forget something. Perhaps the stack overflow occurs because of arithmetic overflow. Since you use Integer, maybe Java "change" those "flying numbers" into a negative number when arithmetic overflow occurs. And as seen in method seqCount(int), you don't check invariant n > 0.
You can solve this problem not only with recursion but also with a single loop. there is overflow if you write int. because it generates long while chaning and the recursion never ends because never equal to 1 and you probably get stackoverflow error
Here is my solution with loop and recursion:
public class Collatz {
public int getChainLength(long i) {
int count = 1;
while (i != 1) {
count++;
if (i % 2 == 0) {
i /= 2;
} else {
i = 3 * i + 1;
}
}
return count;
}
public static int getChainLength(long i, int count) {
if (i == 1) {
return count;
} else if (i % 2 == 0) {
return getChainLength(i / 2, count + 1);
} else {
return getChainLength(3 * i + 1, count + 1);
}
}
public int getLongestChain(int number) {
int longestChain[] = { 0, 0 };
for (int i = 1; i < number; i++) {
int chain = getChainLength(i);
if (longestChain[1] < chain) {
longestChain[0] = i;
longestChain[1] = chain;
}
}
return longestChain[0];
}
/**
* #param args
*/
public static void main(String[] args) {
System.out.println(new Collatz().getLongestChain(1000000));
}
}
Here you can have a look at my recursive implementation of problem 14:
http://chmu.bplaced.net/?p=265
import java .util.*;
public class file
{
public static void main(String [] args)
{
long largest=0;
long number=0;
for( long i=106239;i<1000000;i=i+2)
{
long k=1;
long z=i;
while(z!=1)
{
if(z%2==0)
{
k++;
z=z/2;
} else{
k++;
z=3*z+1;
}
}
if(k>largest)
{
number=i;
largest=k;
System.out.println(number+" "+largest);
}
}//for loop
}//main
}

Categories