Minimum array value incorrect using recursion - java

I am trying to create a method to search a 1D array for a minimum value using recursion. It does give me an output but it is always "1" regardless of whether or not the array even contains "1". I am very new to programming and any help is appreciated.
public static int smallest(int[] array)
{
return smallestFrom(array, 0);
}
static int min = 500; //large number
private static int smallestFrom(int[] array, int i)
{
int x = array.length;
if (i < x && array[i] < min)
{
min = array[i];
i++;
smallestFrom(array, i);
}
else if (i < x && array[i] >= min)
{
i++;
smallestFrom(array, i);
}
return min;
}
Output:
2,4,6,1,6,3,8
Smallest: 1
43,76,3,23,95,23
Smallest: 1

Your implementation looks fine to me. Well, that's a bit too much said, but it works. You could improve this quite a bit though:
Large Integer
Why use some arbitrary number as "large number"? This code will break for inputs with larger values than 500. You should just use the constant Integer.MAX_VALUE. There are no larger values possible than this one, it's named in a clear manor and it's defined by the API.
Global variables
This is where the error occurs. Your implementation is designed for singleuse. min will hold 1 after running it with the first array. Since there are no numbers larger than 1 in the second example-array, it will return 1 again. This can be fixed by either resetting min to the original value each time smallest is called, or alternatively completely relinquishing it (see below).
Branching
This problem can be solved with a lot less conditions. Instead of storing the minimum, we could use an alternate definition of the maximum of an array:
max({a, b, c, d, e, f}) = max({a, max({b, c, d, e, f})})
Looks more complicated? Actually it isn't. The idea is that the maximum of an array is the maximum of it's first elements and the maximum of all remaining elements in the array. This could now be translated a lot simpler into code.
Putting it all together
static int min(int[] arr)
{
return minRec(arr, 0);
}
static int minRec(int[] arr, int i)
{
if(i == arr.length)
return Integer.MAX_VALUE;
return Math.min(arr[i], minRec(arr, i + 1));
}
Looks a lot neater, doesn't it? Math.min(int, int) is just the API-implementation of a function that returns the minimum of two parameters.

Related

Dynamic Programming Problem: Minimizing A Path Through Array

I'm working on a problem right now where we are provided with a 1D array of values, and must find the path from the first index to the last index that sums to the smallest sum. The only restrictions are that if you go forward, the distance you go must be 1 more than the last "jump", while if you go backwards, you must go the same distance as the last "jump". For instance, given an array int[] values = new int[]{4, 10, 30, 1, 6}, you need to find the path that gets you from position 0 (4) to position 4 (6) that sums up to the smallest amount. The starting indice is not counted, thus, if I go from values[0] to values[1] (which is the only possible starting move), my running total at that point would be 10. From there, I either have the choice to "jump" back the same distance (to values[0]), or "jump" one distance longer than my last jump, which would then be 1+1=2, so jump from values[1] to values[3].
I'm really new to dynamic programming and attempted a solution that went something like this
public static int smallestCalc(int[] values, int prevJump, int pos, int runTot) {
while (pos != penal.length) {
int forwards = 600;
int backwards = 600;
try {
backwards = penal[pos - prevJump];
} catch (Exception ignore) {}
try {
forwards = penal[pos + prevJump+1];
} catch (Exception ignore) {}
int min = Math.min(forwards,backwards);
if (min == backwards) {
pos -= prevJump;
} else {
pos += prevJump + 1;
prevJump ++;
}
runTot+=min;
smallestCalc(values, prevJump, pos, runTot);
}
return runTot;
}
However, I recognize that I'm not actually making use of a dynamic programming table here, but I'm not exactly sure what I would store inside that I need to "remember" across calculations, or how I could even utilize it in calculations. From what I see, it appears that I basically have to make a recursive function that evaluates all possible jump distances from an index, store them, and then traverse through the DP table to find the smallest amount? Should I be starting from the last index or the first index of the array to limit possible moves? I watched this video here, and understood the premise, but it seems much more applicable to his 2D Array than anything I have. Any amount of guidance here would be greatly appreciated.
In my opinion, this is a 2D DP problem.
dp(i, j) represents the minimum sum required to reach last index from index i and minimum jump allowed of size j.
Let's say you are at index i in the array. Then you can either go to index i-j+1 or index i+j.
So,
int recur(int values[], int i, int j){
// base case. Here n is size of values array
if(i==n-1)
return 0;
if(dp[i][j] != -1){
/* here -1 is taken as to mark never calculated state of dp.
If the values[] array also contains negative values then you need to change it to
something appropriate.
*/
return dp[i][j];
}
int a = INT_MAX;
int b = a;
if(i>0 && (i-j+1)>=0)
a = values[i-j + 1] + recur(values, i-j+1, j);
if(i+j < n)
b = values[i+j] + recur(values, i+j, j+1);
return dp[i][j] = min(a, b);
}
Time and space complexity O(n * n).
Edit:
Initial function call is recur(values, 0, 1).
I know that the tag of this question is java but I do competitive programming in c++ only. Here I have full working code if you want in c++.

Getting Time limit exceeded error in java

class Check {
static void countOddEven(int a[], int n) {
int countEven = 0, countOdd = 0;
for (int item : a) {
if (item % 2 == 0) {
countEven++;
}
}
countOdd = n - countEven;
System.out.println(countOdd + " " + countEven);
}
}
Code is to calculate even and odd numbers in an array. Please help to optimise the code.
You’re code is not correct.
If you were meant to count the even and odd numbers in a, then you are counting the even numbers correctly. If n is not equal to the length of a, then your calculation of the count of odd numbers is incorrect.
If on the other hand — and I’m just guessing — you were meant to count the even and odd numbers among the first n elements, then you are counting the even numbers incorrectly since you are iterating over all of a. Also in this case, if n is much smaller than the length of a, there is an optimization in only iterating over the first n elements as you should.
Finally you may try the following version. I doubt that it buys you anything, but I am leaving the measurements to you.
int countOdd = 0;
for (int ix = 0; ix < n; ix++) {
countOdd += a[ix] & 1;
}
int countEven = n - countOdd;
The trick is: a[ix] & 1 gives you the last bit of a[ix]. This is 1 for odd numbers and 0 for even numbers (positive or negative). So we are really adding a 1 for each odd number.
You should try running code with for loop instead of for each loop
Because ,
When accessing arrays, at least with primitive data for loop is dramatically faster.
however
When accessing collections, a foreach is significantly faster than the basic for loop’s array access.
but if you are getting some another errors , so might have done something wrong while calling the method (make sure n=length of your array)
here is the whole code with main method.
class Check{
static void countOddEven(int a[], int n){
int countEven=0,countOdd=0;
for(int i=0;i<n;i++)
if(a[i]%2==0)
{
countEven++;
}
countOdd=n-countEven;
System.out.println(countOdd+" "+countEven);
}
public static void main(String[] arg){
int a[]={2,3,4,5,6};
int n = 5;
countOddEven(a,n);
}
}

No. of ways to divide an array

I want to find The number of ways to divide an array into 3 contiguous parts such that the sum of the three parts is equal
-10^9 <= A[i] <= 10^9
My approach:
Taking Input and Checking for Base Case:
for(int i=0;i<n;i++){
a[i]= in.nextLong();
sum+=a[i];
}
if(sum%3!=0)System.out.println("0");
If The answer is not above Then Forming the Prefix and Suffix Sum.
for(int i=1;i<=n-2;i++){
xx+=a[i-1];
if(xx==sum/3){
dp[i]=1;
}
}
Suffix Sum and Updating the Binary Index Tree:
for(int i=n ;i>=3;i--){
xx+=a[i-1];
if(xx==sum/3){
update(i, 1, suffix);
}
}
And Now simple Looping the array to find the Total Ways:
int ans=0;
for(int i=1;i<=n-2;i++){
if(dp[i]==1)
{
ans+= (query(n, suffix) - query(i+1, suffix));
// Checking For the Sum/3 in array where index>i+1
}
}
I Getting the wrong answer for the above approachI don't Know where I have made mistake Please Help to Correct my mistake.
Update and Query Function:
public static void update(int i , int value , int[] arr){
while(i<arr.length){
arr[i]+=value;
i+=i&-i;
}
}
public static int query(int i ,int[] arr){
int ans=0;
while(i>0){
ans+=arr[i];
i-=i&-i;
}
return ans;
}
As far as your approach is concerned its correct. But there are some points because of which it might give WA
Its very likely that sum overflows int as each element can magnitude of 10^9, so use long long .
Make sure that suffix and dp array are initialized to 0.
Having said that using a BIT tree here is an overkill , because it can be done in O(n) compared to your O(nlogn) solution ( but does not matter if incase you are submitting on a online judge ).
For the O(n) approach just take your suffix[] array.And as you have done mark suffix[i]=1 if sum from i to n is sum/3, traversing the array backwards this can be done in O(n).
Then just traverse again from backwards doing suffix[i]+=suffix[i-1]( apart from base case i=n).So now suffix[i] stores number of indexs i<=j<=n such that sum from index j to n is sum/3, which is what you are trying to achieve using BIT.
So what I suggest either write a bruteforce or this simple O(n) and check your code against it,
because as far as your approach is concerned it is correct, and debugging is something not suited for
stackoverflow.
First, we calculate an array dp, with dp[i] = sum from 0 to i, this can be done in O(n)
long[]dp = new long[n];
for(int i = 0; i < n; i++)
dp[i] = a[i];
if(i > 0)
dp[i] += dp[i - 1];
Second, let say the total sum of array is x, so we need to find at which position, we have dp[i] == x/3;
For each i position which have dp[i] == 2*x/3, we need to add to final result, the number of index j < i, which dp[j] == x/3.
int count = 0;
int result = 0;
for(int i = 0; i < n - 1; i++){
if(dp[i] == x/3)
count++;
else if(dp[i] == x*2/3)
result += count;
}
The answer is in result.
What wrong with your approach is,
if(dp[i]==1)
{
ans+= (query(n, suffix) - query(i+1, suffix));
// Checking For the Sum/3 in array where index>i+1
}
This is wrong, it should be
(query(n, suffix) - query(i, suffix));
Because, we only need to remove those from 1 to i, not 1 to i + 1.
Not only that, this part:
for(int i=1;i<=n-2;i++){
//....
}
Should be i <= n - 1;
Similarly, this part, for(int i=n ;i>=3;i--), should be i >= 1
And first part:
for(int i=0;i<n;i++){
a[i]= in.nextLong();
sum+=a[i];
}
Should be
for(int i=1;i<=n;i++){
a[i]= in.nextLong();
sum+=a[i];
}
A lot of small errors in your code, which you need to put in a lot of effort to debugging first, jumping to ask here is not a good idea.
In the question asked we need to find three contiguous parts in an array whose sum is the same.
I will mention the steps along with the code snippet that will solve the problem for you.
Get the sum of the array by doing a linear scan O(n) and compute sum/3.
Start scanning the given array from the end. At each index we need to store the number of ways we can get a sum equal to (sum/3) i.e. if end[i] is 3, then there are 3 subsets in the array starting from index i till n(array range) where sum is sum/3.
Third and final step is to start scanning from the start and find the index where sum is sum/3. On finding the index add to the solution variable(initiated to zero), end[i+2].
The thing here we are doing is, start traversing the array from start till len(array)-3. On finding the sum, sum/3, on let say index i, we have the first half that we require.
Now, dont care about the second half and add to the solution variable(initiated to zero) a value equal to end[i+2]. end[i+2] tells us the total number of ways starting from i+2 till the end, to get a sum equal to sum/3 for the third part.
Here, what we have done is taken care of the first and the third part, doing which we have also taken care of the second part which will be by default equal to sum/3. Our solution variable will be the final answer to the problem.
Given below are the code snippets for better understanding of the above mentioned algorithm::-
Here we are doing the backward scanning to store the number of ways to get sum/3 from the end for each index.
long long int *end = (long long int *)calloc(numbers, sizeof(long long int);
long long int temp = array[numbers-1];
if(temp==sum/3){
end[numbers-1] = 1;
}
for(i=numbers-2;i>=0;i--){
end[i] = end[i+1];
temp += array[i];
if(temp==sum/3){
end[i]++;
}
}
Once we have the end array we do the forward loop and get our final solution
long long int solution = 0;
temp = 0;
for(i=0;i<numbers-2;i++){
temp+= array[i];
if(temp==sum/3){
solution+=end[i+2];
}
}
solution stores the final answer i.e. the number of ways to split the array into three contiguous parts having equal sum.

How do you recursively count the number of negative numbers in an array (Java)?

I need to use this method:
public static int countNegative(double[] numbers, int count){ }
to count the number of negative numbers in a double array. I could easily do it if I could include a 3rd parameter, sum, but I can only use the array and an int. I'm completely stuck. I've tried a few things, but cannot get it right. I've gotten everything from the size of the array to ArrayIndexOutOfBounds, but never the right answer. Could anyone help me out with this?
-EDIT-
Well here is the exact assignment:
Write a program that reads in a sequence of numbers (not necessary integers) from standard input until 0 is read, and stores them in an
array, similar to what you did in assignment 2. This part is done
using iteration . You may assume that there will not be more than 100
numbers.
Then compute the maximum number stored in the array, the count of
negative numbers, and compute the sum of positive numbers, using
recursion. Thus you will create recursive methods findMax,
countNegative, and computeSumPositive in Assignment9 class and they
will be called by a main method.
Specifically, the following recursive methods must be implemented
(These method should not contain any loop):
public static double findMax(double[] numbers, int count) -> It finds the maximum number in the array, count is the number of elements
in the array
public static int countNegative(double[] numbers, int count) ->
counts the negative integers
public static double computeSumPositive(double[] numbers, int count)
-> sums number of positive integers
findMax() was easy:
public static double findMax(double[] numbers, int count){
if(numbers.length - 1 == count)
return numbers[count];
else
return Math.max(numbers[count], findMax(numbers, count+1));
}
This is my most recent attempt at countNegative. It just returns 99 (I have the array initialized with 100 elements):
public static int countNegative(double[] numbers, int count){
int i=0;
if(numbers[count]<0)
i=1;
if(numbers.length-1==count)
return count;
else
return i+countNegative(numbers,count+1);
}
I should be able to figure out the computeSumPositive if I can figure out this negative one.
Count can be whatever you need it to be. I used it more as an index in findMax.
What is the use of count? It would make sense if it is index:
public static int countNegative(double[] numbers, int index)
{
if(index == numbers.length) return 0;
return (numbers[index] < 0 ? 1 : 0) + countNegative(numbers, index + 1);
}
and call it like this:
int count = countNegative(array, 0);
Use the int parameter as an index into the numbers array. Determine if the current index's value is negative (count 0 or 1 here). Then return the sum of that 0/1 count and the recursive call that looks at the next index position. The base case is when you've run past the end of the array, which returns 0.
public static int countNegative(double[] numbers, int count){
if(count == numbers.length){
return 0;
}
int sum = countNegative(numbers, count + 1);
if(numbers[count] < 0){
sum++;
}
return sum;
}
You call this method: countNegative(numbers, 0);
count is to be used as the base condition of recursion. You return the result back up the stack
Example:
double a[]={-12.0,1.0,0.0,23.0,-23.0,-9.0};
System.out.println(countNegative(a, 0));
I get 3 in console
Start by implementing it for an array with 0 elemtents. The for an array of 1 element. The for an array of more,usign the previous results...
here's how it might work
public static int countNegative(double[] numbers){
int result = numbers[0] < 0 ? 1 : 0;
if(numbers.length > 1) {
result += countNegative(Arrays.copyOfRange(numbers, 1, numbers.length));
}
return result;
}
You don't need the count parameter because of the way recursion works. when you call the function with an array it first determines if the first element is less than zero, making it negative. Next it checks if the array has more than one element, and if it does it calls itself with everything but the first element of the array and adds that to the result.
After that it returns the result which depending if it's in a recursive call or not, will either add it to the result of the call above it or give it back to the person calling it.

Project Euler 14: Issue with array indexing in a novel solution

The problem in question can be found at http://projecteuler.net/problem=14
I'm trying what I think is a novel solution. At least it is not brute-force. My solution works on two assumptions:
1) The less times you have iterate through the sequence, the quicker you'll get the answer. 2) A sequence will necessarily be longer than the sequences of each of its elements
So I implemented an array of all possible numbers that could appear in the sequence. The highest number starting a sequence is 999999 (as the problem only asks you to test numbers less than 1,000,000); therefore the highest possible number in any sequence is 3 * 999999 + 1 = 2999998 (which is even, so would then be divided by 2 for the next number in the sequence). So the array need only be of this size. (In my code the array is actually 2999999 elements, as I have included 0 so that each number matches its array index. However, this isn't necessary, it is for comprehension).
So once a number comes in a sequence, its value in the array becomes 0. If subsequent sequences reach this value, they will know not to proceed any further, as it is assumed they will be longer.
However, when i run the code I get the following error, at the line introducing the "wh:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3188644
For some reason it is trying to access an index of the above value, which shouldn't be reachable as it is over the possible max of 29999999. Can anyone understand why this is happening?
Please note that I have no idea if my assumptions are actually sound. I'm an amateur programmer and not a mathematician. I'm experimenting. Hopefully I'll find out whether it works as soon as I get the indexing correct.
Code is as follows:
private static final int MAX_START = 999999;
private static final int MAX_POSSIBLE = 3 * MAX_START + 1;
public long calculate()
{
int[] numbers = new int[MAX_POSSIBLE + 1];
for(int index = 0; index <= MAX_POSSIBLE; index++)
{
numbers[index] = index;
}
int longestChainStart = 0;
for(int index = 1; index <= numbers.length; index++)
{
int currentValue = index;
if(numbers[currentValue] != 0)
{
longestChainStart = currentValue;
while(numbers[currentValue] != 0 && currentValue != 1)
{
numbers[currentValue] = 0;
if(currentValue % 2 == 0)
{
currentValue /= 2;
}
else
{
currentValue = 3 * currentValue + 1;
}
}
}
}
return longestChainStart;
}
Given that you can't (easily) put a limit on the possible maximum number of a sequence, you might want to try a different approach. I might suggest something based on memoization.
Suppose you've got an array of size 1,000,000. Each entry i will represent the length of the sequence from i to 1. Remember, you don't need the sequences themselves, but rather, only the length of the sequences. You can start filling in your table at 1---the length is 0. Starting at 2, you've got length 1, and so on. Now, say we're looking at entry n, which is even. You can look at the length of the sequence at entry n/2 and just add 1 to that for the value at n. If you haven't calculated n/2 yet, just do the normal calculations until you get to a value you have calculated. A similar process holds if n is odd.
This should bring your algorithm's running time down significantly, and prevent any problems with out-of-bounds errors.
You can solve this by this way
import java.util.LinkedList;
public class Problem14 {
public static void main(String[] args) {
LinkedList<Long> list = new LinkedList<Long>();
long length =0;
int res =0;
for(int j=10; j<1000000; j++)
{
long i=j;
while(i!=1)
{
if(i%2==0)
{
i =i/2;
list.add(i);
}
else
{
i =3*i+1;
list.add(i);
}
}
if(list.size()>length)
{
length =list.size();
res=j;
}
list.clear();
}
System.out.println(res+ " highest nuber and its length " + length);
}}

Categories

Resources