I've been practicing recursion, trying to get more comfortable with it, but this one problem keeps bugging me.
I'm supposed to write a recursive program that triples each element of an array. At first, it seemed simple enough.
public static void triple (int[] a, int index) {
if (index < a.length()) {
a[index]*=3;
triple(a, index + 1);
}
}
But when I looked at the problem again, I realized that I'd made a mistake. The parameters for the method are only supposed to be an integer array with no index.
How do I go about solving this?
This problem is not the best problem to be solved with recursion.
Leave the method as it is (replace length() with length only).
Overload it with another method:
public static void triple(int[] a) {
triple(a, 0);
}
Then in your code you can go for:
int[] t = {1, 2, 3};
triple(t);
The problem is: this problem can't be really solved using recursion - assuming that you only can pass down the array itself.
The point is: you have to somehow know which indexes have been tripled; and which not.
In other words: you somehow have to cheat; you would have to keep some helper variable somewhere that tells you about the last processed index; or something alike.
But as said; that would mean to implement a solution ... that can only work by "massaging" the requirements.
Meaning: when you really restrict yourself to one method that takes just the array as argument, then you can't solve this puzzle!
Related
public static int rFib(int n) {
if(n == 0) {
return 0;
}
if(n == 1) {
return 1;
}
return n + rFib(n-1);
}
I am trying to find the largest number that will compute in under 60 seconds. Then I will use an iterative method to compare. Any number greater than 10,000 gives a stack-overflow error. How do I avoid this?
One solution to this recursion problem is to break the recursion using dynamic programming. For example, memoization can be applied and allow you to implement it like
private static Map<Integer, Integer> memo = new HashMap<>();
static {
memo.put(0, 0);
memo.put(1, 1);
}
public static int rFib(int n) {
if (memo.containsKey(n)) {
return memo.get(n);
}
int r = rFib(n - 2) + rFib(n - 1);
memo.put(n, r);
return r;
}
Unfortunately, you have come across the problem which is both the single most-used example for understanding recursion and almost the single worst application to apply recursion to.
It's really simple to understand recursion from the fibonacci because it's a really trivial recursive algorithm for you to explain to somebody and understand... Which means it's great for programming recursion, right? Unfortunately, no.
I apologize if I'm going to tell you things you already know, but I know that fibonacci is one of the first examples in introductory programming so I'm assuming that's where you're coming from.
There's a thing in programming called a stack. It's literally called this because it's like a stack of papers. When you call a function, it puts onto the stack all the information needed to call the function, pass the arguments, and know how to return from the function (and some other administrative stuff). When that function recursively calls itself, it puts another sheet on top of the stack. Then that function puts another sheet. These sheets aren't removed until the function finishes... But since one function can't finish before the other one finishes, it just grows and grows and grows.
And the stack is only so big. Purposely. To avoid this problem.
Normally, recursion isn't used for such deep problems. (Tail-call-recursive people: ignore this; if you don't know what tail-call-recusion is: also ignore this.)
The way to fix this is to not do it. It's generally recognized that in nearly every arbitrarily-recursive function application, a for loop will work better (and faster).
i have sth like: ( X - different algorithms)
public class XAlgorithm{
sort(List l){...}
}
In testClass it present as follows:
ArrayList array = new ArrayList(...); // original array
public static void main(String[]args){
AlgorithmsTest at = new AlgorithmsTest();
at.testInsertSort();
// when add at.array.printAll() - method printing all elements, there are no changes to original array what I want
at.testBubbleSort();
at.testSelectSort();
at.testShellSort();
}
testBubbleSort{
...
ArrayList arrayBubble = new ArrayList(testBubble.sort(array));
...
}
Problem is my result ( time measured by System.currentTimeMilis() ) is different when i launch for ex. two times in a row the same algorithm, it's also strange because even when I done copying in every method ( by putting all new Elements into new array and then operate on it) still works wrong. Time is always greatest for first algorithm in main no matter which one it is.
I even controlled array between every algorithm ( like //comment in code above) and it is right - no changes to it, so where is the problem :/ ?
Thanks in advance
Even though you stated you're making a copy of the array, it sounds like you're sorting in place and then making a copy of the array.
Therefore, the first time is going to take longest, but all subsequent runs have less work to do because the array is "sorted".
It also seems to say that your sort algorithms have bugs in it, such that you're getting close on the first sort (or it is right) but then a subsequent sort is finding a corner case, causing a slight variation in the sorted array. I'd be analyzing my sort methods and make sure they're working as you intended.
I need to develop a recursive program that can calculate the result 1/i+2/(i-1)+3/(i-2)+…+(i-1)/2+i/1 when f3(1, i) is called.
public class Project4f3
{
public static int f3(int x, int y)
// I know that it has to have a stop termination and i think that is when x==y, but im not sure
if (x==y) return ??
else return f3(x+1,y-1)
// don't think this is right but this is where I am at right now
}
public static void main(String[] args)
{
System.out.print(f3(1,i));
}
}
To develop a recursive algorithm, you need to think about two things:
What are the base cases? These are the cases that can be computed directly. For instance, if n == 1, you can compute the answer directly.
What are the recursive cases? These are the cases that assume that the solution to a reduced problem is available (via a recursive call) and build on that. For instance, if you know the answer for n - 1, how would you use that to compute the answer for n?
Once you've identified those, you are then ready to define and code your recursive method(s).
(I should point out that the n that I'm using here is not necessarily the i you used in your equation. It might make more sense to use the number of terms in the equation as n, or perhaps the number of elements on either side of the middle term. The creative part of recursive problem-solving—and also often the most difficult—is coming up with the right problem representation.)
I'm trying to make a recursive method that receives an array and traverse it like with a loop, but without a loop.
Couldn't find a way to make an index, and increase each time I call the method.
If you have a function f(array,index) make it do something with array[index] and return function(array,index+1). Finally, to start it off call function(array,0). If there are any variables or state you are building up over the course of the recursive function, also pass it via the arguments.
A shot in the dark, but
public void printMyArray (String[] test, int index) {
// verify the index isn't too large
// Grab a value and do something with it.
}
Edit: As stated above, you basically just need to run through each value in the array. The easiest is really carrying over an index value (in my opinion).
Given the need to loop up to an arbitrary int value, is it better programming practice to convert the value into an array and for-each the array, or just use a traditional for loop?
FYI, I am calculating the number of 5 and 6 results ("hits") in multiple throws of 6-sided dice. My arbitrary int value is the dicePool which represents the number of multiple throws.
As I understand it, there are two options:
Convert the dicePool into an array and for-each the array:
public int calcHits(int dicePool) {
int[] dp = new int[dicePool];
for (Integer a : dp) {
// call throwDice method
}
}
Use a traditional for loop:
public int calcHits(int dicePool) {
for (int i = 0; i < dicePool; i++) {
// call throwDice method
}
}
My view is that option 1 is clumsy code and involves unnecessary creation of an array, even though the for-each loop is more efficient than the traditional for loop in Option 2.
At this point, speed isn't important (insert premature-optimization comment ;). What matters is how quickly you can understand what the code does, which is to call a method dicePool times.
The first method allocates an array of size dicePool and iterates through its values, which happens to run the loop body dicePool times (I'll pretend you meant int instead of Integer to avoid the unrelated autoboxing issue). This is potentially inefficient for the computer running the code, but more importantly it's inefficient for the human reading the code as it's conceptually distant from what you wanted to accomplish. Specifically, you force the reader to think about the new array you've just made, AND the value of the variable a, which will be 0 for every iteration of the loop, even though neither of those are related to your end goal.
Any Java programmer looking at the second method will realize that you're executing the loop body dicePool times with i 'counting up' to dicePool. While the latter part isn't especially important, the beginning is exactly what you meant to do. Using this common Java idiom minimizes the unrelated things a reader needs to think about, so it's the best choice.
When in doubt, go with simplicity. :D
Why would you need to allocate an array to loop over a variable that can be safely incremented and used without any need of allocation?
It sounds unecessarily inefficient. You can need to allocate an array if you need to swap the order of ints but this is not the case. I would go for option 2 for sure.
The foreach is useful when you want to iterate on a collection but creating a collection just to iterate over it when you don't need it is just without sense..
(2) is the obvious choice because there's no point in creating the array, based on your description. If there is, of course things change.
What makes you think that the for-each loop is more efficient?
Iterating over a set is very likely less efficient than a simple loop and counter.
It might help if you gave more context about the problem, specifically whether there's more to this question than choosing one syntax over the other. I am having trouble thinking of a problem to which #1 would be a better solution.
I wouldn't write the first one. It's not necessary to use the latest syntax in every setting.
Your instinct is a good one: if it feels and looks clumsy, it probably is.
Go with #2 and sleep at night.