i wrote the following codes
my aim is to get the lowst value of doble[] absOfSub but it gives the following exception
at line compared= Double.compare(d2, d1);
Exception in thread "main" java.lang.StackOverflowError
why overflow and how to fix it?
EDIT
public class TestThe {
static double[] absOfSub = new double[5];
private static int index=0;
private static int compare(int currentIdx, int minIdx) {
if(index < absOfSub.length) {
if(absOfSub[currentIdx] < absOfSub[minIdx]) {
compare(currentIdx + 1, currentIdx);
} else {
compare(currentIdx + 1, minIdx);
}
}
return minIdx;
}
public static void main(String[] args) {
absOfSub[0]=1000;
absOfSub[1]=810;
absOfSub[2]=108;
absOfSub[3]=130;
absOfSub[4]=110;
double result;
int inndex= compare(0,1);
System.out.println(absOfSub[inndex]);
}
}
How about this simple and elegant solution?
static double min(double... ds) {
double min = Double.POSITIVE_INFINITY;
for (double d : ds) min = Math.min(min, d);
return min;
}
public static void main(String[] args) {
System.out.println(min(-5.2, 0, -10.1, 3));
}
Recursive solution (not recommended!):
static double minRecur(double... ds) {
return minRecur(ds, 0, Double.POSITIVE_INFINITY);
}
static double minRecur(double[] ds, int i, double runningMin) {
return (i < 0 || i >= ds.length)?
runningMin : minRecur(ds, i + 1, Math.min(runningMin, ds[i]));
}
You don't change the value of index inside your method. So this recursive method call won't stop at all.
You never manipulate the value of the index variable. You see another reason why people should try to limit the number of static variables they use. Let me try to help you:
public class TestThe {
private static double[] absOfSub = new double[5];
private static void compare(int currentIdx, int minIdx) {
if(currentIdx < absOfSub.length) {
if(absOfSub[currentIdx] < absOfSub[minIdx]) {
return compare(currentIdx + 1, currentIdx);
} else {
return compare(currentIdx + 1, minIdx);
}
} else {
return minIdx;
}
}
public static void main(String[] args) {
absOfSub[0] = 10;
absOfSub[1] = 810;
absOfSub[2] = 108;
absOfSub[3] = 130;
absOfSub[4] = 110;
System.out.println("The minimum value is: " + absOfSub[compare(0, 0)]);
}
}
EDIT Some more notes:
always specify the attribute accessor as private, when this is the intention
always format your code
when you write recursion, make sure you always change something for every consequent call and that it gets you closer to the ending condition.
double primitive type itself defines a comparison operator, no need to use Double.compare in your case.
You don't actually change the index variable, so the recursion will never end. But there is a lot more wrong with this.
An easy generic way to find the minimal value in an array, without using recursion:
int min = Integer.MAX_VALUE;
for( int i = 0; i < array.length; i++ ) {
// Math.min returns the lower value of the two arguments given
min = Math.min( min, array[i] );
}
return min;
This could be easily adapted to fit your needs.
Index in each routine is having either 0 or 1 or 2 as the value.
Related
I wrote two pieces of code for knapsack problem. The first code gives me the correct answer (which is 16) and the second one doesn't. Is it something wrong with my recursive function?
First code (correct answer):
public class knapsackProblem {
static int[] weight = {1,2,4,2,5};
static int[] value = {5,3,5,3,2};
int result = 0;
// recursive function
public int sack(int i, int cap)
{
//base case
if(i<0 || cap == 0)
{
return 0;
} else if(weight[i] > cap)
{
return sack(i-1, cap);
} else
{
//get maximum value
return Math.max(sack(i-1, cap), value[i] + sack(i-1, cap - weight[i]));
}
}
public static void main(String[] args)
{
int capacity = 10;
int len = weight.length;
knapsackProblem kp = new knapsackProblem();
int total = kp.sack(len - 1, capacity);
System.out.println("sacked array is " + total);
}
}
Second code (incorrect answer):
public class knapsackProblem {
static int[] weight = {1,2,4,2,5};
static int[] value = {5,3,5,3,2};
int result = 0;
int tempNO = 0;
int tempYES = 0;
// recursive function
public int sack(int i, int cap)
{
//base case
if(i<0 || cap == 0)
{
return 0;
} else if(weight[i] > cap)
{
return sack(i-1, cap);
} else
{
//no case, move on to next value
tempNO = sack(i-1, cap);
//yes case, add the current value and move on to next value with decreased capacity
tempYES = value[i] + sack(i-1, cap - weight[i]);
//get maximum value
return Math.max(tempNO, tempYES);
}
}
public static void main(String[] args)
{
int capacity = 10;
int len = weight.length;
knapsackProblem kp = new knapsackProblem();
int total = kp.sack(len - 1, capacity);
System.out.println("sacked array is " + total);
}
}
The only difference is that in second code I put the results from recursion into variables before comparing for maximum value.
Thanks
Your variables are attributes of the class. The recursive calls are modifying those attributes every time, because you're using one single instance of the class to make the calls to the function. Declare the variables inside the method and remove them from the class to make it work. :)
I've got 2 integer values, e.g. a = 10 and b = 20.
Now i want to substract them: a - b, but as a result i don't want to have negative values, so in this example i want the result 0 and a new integer variable with the rest (10 here).
Two more examples:
Input: a=40, b=20; Expected Output:20
input: a=25 b=50 Expected Output: 0 and a new int var = 25
How to do this in java without external libraries?
From what I understand, you want a variable to be holding the result if the result is greater than or equal to 0. Otherwise, that variable should hold 0 and another variable will hold a positive value of the result.
If this is the case, consider the following code snippet:
int result = a -b;
int otherVariable = 0;
if (result < 0) {
otherVariable = -result;
result = 0;
}
int aMinusB = a-b;
int output = Math.max(aMinusB,0);
int rest = aMinusB < 0 ? Math.abs(aMinusB) : 0;
https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html
There are two ways to solve this problem: -
First: -
If you don't want to create a method to return this value and only to display it, then you can do it by printing out the results of if-else block in the code below within the function itself.
Second: -
If you want to use the result somewhere else, go for an object based approach: -
// Main class
public class SubtractWithRest {
public static void main(String[] args) {
SubtractResultWithRest subtractResultWithRest = new SubtractResultWithRest();
subtraction(10, 20, subtractResultWithRest);
System.out.println("Result: " + subtractResultWithRest.getResult());
System.out.println("Rest: " + subtractResultWithRest.getRest());
}
private static void subtraction(int num1, int num2, SubtractResultWithRest subtractResultWithRest) {
if (num2 > num1) {
subtractResultWithRest.setResult(0);
subtractResultWithRest.setRest(num2 - num1);
} else {
subtractResultWithRest.setResult(num1 - num2);
}
}
}
// Object class
public class SubtractResultWithRest {
private int result;
private int rest = 0;
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public int getRest() {
return rest;
}
public void setRest(int rest) {
this.rest = rest;
}
}
the code below is meant to count each time character 'x' occurs in a string but it only counts once ..
I do not want to use a loop.
public class recursionJava
{
public static void main(String args[])
{
String names = "xxhixx";
int result = number(names);
System.out.println("number of x: " + result);
}
public static int number (String name)
{
int index = 0, result = 0;
if(name.charAt(index) == 'x')
{
result++;
}
else
{
result = result;
}
index++;
if (name.trim().length() != 0)
{
number(name);
}
return result;
}
}
You could do a replacement/removal of the character and then compare the length of the resulting string:
String names = "xxhixx";
int numX = names.length() - names.replace("x", "").length(); // numX == 4
If you don't want to use a loop, you can use recursion:
public static int number (String name)
{
if (name.length () == 0)
return 0;
int count = name.charAt(0)=='x' ? 1 : 0;
return count + number(name.substring(1));
}
As of Java 8 you can use streams:
"xxhixx".chars().filter(c -> ((char)c)=='x').count()
Previous recursive answer (from Eran) is correct, although it has quadratic complexity in new java versions (substring copies string internally). It can be linear one:
public static int number(String names, int position) {
if (position >= names.length()) {
return 0;
}
int count = number(names, position + 1);
if ('x' == names.charAt(position)) {
count++;
}
return count;
}
Your code does not work because of two things:
Every time you're calling your recursive method number(), you're setting your variables index and result back to zero. So, the program will always be stuck on the first letter and also reset the record of the number of x's it has found so far.
Also, name.trim() is pretty much useless here, because this method only removes whitespace characters such as space, tab etc.
You can solve both of these problems by
making index and result global variables and
using index to check whether or not you have reached the end of the String.
So in the end, a slightly modified (and working) Version of your code would look like this:
public class recursionJava {
private static int index = 0;
private static int result = 0;
public static void main(String[] args) {
String names = "xxhixx";
int result = number(names);
System.out.println("number of x: " + result);
}
public static int number (String name){
if(name.charAt(index) == 'x')
result++;
index++;
if(name.length() - index > 0)
number(name);
return result;
}
}
You can use StringUtils.countMatches
StringUtils.countMatches(name, "x");
I'm using arraylist to implement a queue. Everything is going good except when I try to find the minimum value of the queue it does not work properly and the dequeue and peek functions for some reason do not work as expected. I tried going through line by line but I don't understand what is going wrong in the min() function:
public class queuePractice {
static ArrayList<Integer>nums = new ArrayList<Integer>();
static int top = -1;
public static void main(String[] args) {
enqueue(5);
enqueue(2);
enqueue(6);
enqueue(3);
enqueue(12);
enqueue(1);
enqueue(20);
System.out.println("The min is: " + min());
}
public static int peek() {
return nums.get(0);
}
public static void enqueue(int x) {
nums.add(++top, x);
}
public static int dequeue() {
top--;
return nums.remove(0);
}
public static void display() {
for(int x = 0; x <=top; x++) {
System.out.print(nums.get(x) + " ");
}
System.out.println();
}
public static boolean isEmpty() {
return top==-1;
}
public static int min() {
int min = Integer.MAX_VALUE;
while(min > peek()) {
min = peek();
dequeue();
}
return min;
}
}
The peek function keeps returning 2 over and over, even if I change the while loop to a for loop. For some reason it is not updating its value whenever I dequeue it? But going through line by line I can't understand what's wrong.
An easier method would be
List<Integer>nums = Arrays.asList(5,2,35,6); // or use your enqueue
Iterator<Integer> it = nums.iterator();
int min = Integer.MAX_VALUE;
while (it.hasNext()) {
Integer i = it.next();
min = Math.min(i, min);
}
System.out.println(min);
Of course any type of looping around the List would work
Did you mean your code is printing 2 all the time? That's because your min() method always terminate on 2
First iteration your int min value will be 5
Second iteration your int min value will be 2
Third iteration your loop will exit since 2 is not bigger than 6
Then your method will return 2
hope it helps
Here I am working on the following problem where we are given n types of coin denominations of values v(1) > v(2) > ... > v(n) (all integers) The following code tries to find the minimum number of coins that are required to make a sum-C. Here the C is 100(see main function).When I run the code, error--"java.lang.StackOverflowError" comes. Please help.
import java.util.ArrayList;
public class Problem2 {
public static int count=4;
public static int []v={25,10,5,1}; //Array storing denominations
private static int findminimum(ArrayList<Integer> v2) {
int count=v2.get(0);
for(int i=0;i<v2.size();i++)
{
if(count>v2.get(i))
{
count=v2.get(i);
}
}
return count;
}
public static int countmincoins(int n)
{
int t;
if(n<0)
{
t=Integer.MAX_VALUE-100 ;
}
if(n==0)
{
t= 0;
}
else
{
ArrayList<Integer> a=new ArrayList<Integer>();
for(int i=0;i<v.length;i++)
{
int temp=0;
temp=countmincoins(n-v[i])+1; //Stackoverflow error
a.add(temp);
}
t=findminimum(a);
}
return t;
}
public static void main(String args[])
{
System.out.println(countmincoins(100));
}
}
If you use recursion then you need to reach a condition to terminate the recursion. But in your code I do not seen any termination logic. Thats why, it get to infinite loop and StackOverflowException. In your code you use following code to terminate.
if(n==0)
{
t= 0;
}
But here n may not be zero. Becuase countmincoins(n-v[i]) do not ensure you to n will be 0.
Your code is infinite cause t will never be <0 or ==0 given that the values in the array and the condition (n - v[i] )+1, v[i] will always return the same value in every call to the method, therefore infinite recursion.
If your not restricted to using recursion the following would be much simpler:
public static int[] denominations = {25,10,5,1};
public static int minimumCoins(int amount){
int total = 0;
for(int denomination: denominations){
while(amount - denomination >= 0){
amount -= denomination;
total++;
}
}
return total;
}
public static void main(String args[])
{
System.out.println(minimumCoins(98));
}