I was implementing a very simple recursive method to multiply two numbers together. I am very a hard time understanding the basics of recursion.
Is anyone able to explain to me (Line-by-line if possible) how this code works? I am especially confused about the base case is written to return 0 when in reality the actual multiplication is returned instead.
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n; //Recursive Case - Decrements m, while adding n
}
Thanks for any help
I will try to make this answer beginner friendly. First I will answer this part of your question:
I am especially confused about the base case is written to return 0
when in reality the actual multiplication is returned instead.
The value returned in the base case depends on how you are implementing your algorithm. Here in order to calculate n*m, we extend this multiplication to addition. A few examples will make this more clear.
2*3 = 2 + 2 + 2 + 0
4*1 = 4 + 0
5*5 = 5 + 5 + 5 + 5 + 5 + 0
n*m = n + n + n + ... + (m times) + 0
That is why we return 0 in the base case, we have to stop the recursion without making any change in the result and that is only possible if we add 0.
Here is the working of this program:
public static int multiply(int n, int m) {
if (m == 0) {
return 0; //Base case
}
return multiply(n, m - 1) + n;
Let us take n = 4 and m = 3.
Our first call to the method is multiply(4, 3). We then proceed further, the base condition is false so we skip that.
We then get to this part: return multiply(n, m - 1) + n. We make another call to the same function. multiple(4, 2). Again we skip the base case. Here is a table:
multiply(4, 3) -> return multiply (4, 2) + 4
multiple(4, 2) -> return multiply (4, 1) + 4
multiple(4, 1) -> return multiply (4, 0) + 4
multiple(4, 0) -> 0
On substituting the returned values we get,
multiple(4, 3) -> return 0 + 4 + 4 + 4
multiple(4, 2) -> return 0 + 4 + 4
multiple(4, 1) -> return 0 + 4
multiple(4, 0) -> return 0
If our first call is multiply(n, m), then the end returned value is:
multiply (n, m) -> return 0 + n + n + n + ... + (m times)
I hope I have helped you. Try to construct a similar relation like this on your own and you will understand it better. Here is a link on further explanation on recursion:
https://www.geeksforgeeks.org/recursion
I don't understand how this exercise return the number's square. In particular I don't understand the sixth line in which there is return statement and after this "+2*x-1". What is the program behavior in that call?
public class Es {
public static int RecCalc(int x) {
if (x==0) {
return 0;
}else {
return RecCalc(x - 1) + 2 * x - 1;
}
}
public static void main(String[] args) {
System.out.println(RecCalc(3));
}
}
We can see how this works with a little algebra:
(x-1)² + 2x - 1
== x² - 2x + 1 + 2x - 1
== x²
If you are unfamiliar with the formula for (x + y)² then you can do (x-1)² by writing it as (x-1)*(x-1) and using the FOIL method or the distributive property. This is left as an exercise for the reader.
Let's step through, one call at a time.
The first call to kick it all off is:
RecCalc(3);
In Java, the return statement will take everything up to the semi-colon.
So, return 3 + 2 will return 5 to the caller.
RecCalc(3) will result in calling:
RecCalc(2) + 2*3 -1;
RecCalc(2) will result in calling:
RecCalc(1) + 2*2 -1;
RecCalc(1) will result in calling:
RecCalc(0) + 2*1 - 1;
RecCalc(0) will return 0.
Now we can work our way back up the call stack.
RecCalc(0) == 0
RecCalc(1) == RecCalc(0) + 2*1 -1 == (0) + 2*1 -1 == 1
RecCalc(2) == RecCalc(1) + 2*2 -1 == (1) + 2*2 -1 == 4
RecCalc(3) == RecCalc(2) + 2*3 -1 == (4) + 2*3 -1 == 9
This doesn't explain the math, but explains the recursion.
Let's look at the math.
As explained by #CodeApprentice, x² = (x-1)² + 2x -1
The real trick to this whole recursive scheme is the (x-1)².
We know that for x = 4, we can use (x-1)² plus some other junk to get the answer.
But that's just the square of 3 plus some other junk!
Now, to get the square of 3, we know that 3² = (x-1)² plus junk.
But that's just the square of 2 plus some other junk!
And so, we work our way down until we get to a trivial answer, where we return 0. (In fact, you could also return 1 for x=1).
I hope that explains it!
If you have 4 things, you can make a square with side 2:
xx
xx
If you want to make a square with side 3, you need 9 things: add 2 things on each of the side and bottom, plus 1 for the corner:
xx.
xx.
..+
Or, to put it another way, add 3 things on each of the side and bottom, take away 1 for the corner.
Generalizing, if you have a square of side length (n-1), to make a square of side length (n), you have to add on 2 lots of (n-1) things, plus one; or 2 lots of (n) things, take away one.
Hence:
number of things in a square of side length n
= (number of things in a square of side length (n-1))
+ 2 * (n-1) + 1
= (number of things in a square of side length (n-1))
+ 2 * n - 1
Perhaps if you put in a print statement it will help.
public static void main(String[] args) {
System.out.println(RecCalc(5));
}
public static int RecCalc(int x) {
if (x == 0) {
return 0;
} else {
int v = RecCalc(x - 1) + 2 * x - 1;
System.out.println((x-1) + " " + (2*x) + " " + (-1));
return v;
}
}
Prints
0 2 -1
1 4 -1
2 6 -1
3 8 -1
4 10 -1
25
Notice that the value of the sum of the last two columns in each line is an odd number. And the sum of any number of consecutive odd numbers starting with 1 is a perfect square. So essentially, this method just sums up the first x odd numbers.
The problem is I have to print all combinations of a sequence of
numbers from 1 to N that will always result to zero. It is allowed
to insert "+" (for adding) and "-" (for subtracting) between each
numbers so that the result will be zero.
//Output
N = 7
1 + 2 - 3 + 4 - 5 - 6 + 7 = 0
1 + 2 - 3 - 4 + 5 + 6 - 7 = 0
1 - 2 + 3 + 4 - 5 + 6 - 7 = 0
1 - 2 - 3 - 4 - 5 + 6 + 7 = 0
So how can I implement this? I am not asking for the actual
codes to do this, just a hint and ideas to solve this will
do. Thank you..
You could also use recursion here. Just remember your current integer, your max integer, your current sum and some kind of history of operations (could also be your final sequence).
In every level you proceed the path in two dirdctions: adding to your sum and substracting from it.
I did a quick implementation in Python, but it should be easy to transfer this to Java or whatever you are using.
def zero_sum(curr, n, seq, sum):
if curr == n and sum == 0:
print(seq)
elif curr < n:
zero_sum(curr + 1, n, seq + " - " + str(curr + 1), sum - (curr + 1))
zero_sum(curr + 1, n, seq + " + " + str(curr + 1), sum + (curr + 1))
zero_sum(1, 7, "1", 1)
Hopefully you get the idea.
The first step is to turn the problem into an entirely regularly formed problem:
n
∑ ±i = -1
i=2
n-2
∑ ±(i+2) = -1
i=0
The term 1 at the start has no prefix +/-. And the walking index better runs from 0 when using a Java array.
So one has n-1 coefficients -1 or +1 for the possible values.
A brute force approach would be to start with the highest values, i = n-2.
The upper/lower bounds for j = 0, ..., i would be ± (i + 1) * (2 + i + 2) / 2, so one can cut the evaluation there - when the till then calculated sum can no longer reach -1.
To represent the coefficients, one could make a new int[n - 1] or simply a new BitSet(n-1).
public void solve(int n) {
int i = n-2;
int sumDone = 0;
BigSet negates = new BitSet(n - 1);
solveRecursively(i, sumDone, negates);
}
private void solveRecursively(int i, int SumDone, BitSet negates) {
if (i < 0) {
if (sumDone == -1) {
System.out.println("Found: " + negates);
}
return;
}
...
}
The interesting, actual (home) work I leave to you. (With BitSet better i = n, ... , 2 by -1 seems simpler though.)
The question here is how much efficiency matters. If you're content to do a brute-force approach, a regression method like the one indicated by holidayfun is a fine way to go, though this will become unwieldy as n gets large.
If performance speed matters, it may be worth doing a bit of math first. The easiest and most rewarding check is whether such a sum is even possible: since the sum of the first n natural numbers is n(n+1)/2, and since you want to divide this into two groups (a "positive" group and a "negative" group) of equal size, you must have that n(n+1)/4 is an integer. Therefore if neither n nor n+1 is divisible by four, stop. You cannot find such a sequence that adds to zero.
This and a few other math tricks might speed up your application significantly, if speed is of the essence. For instance, finding one solution will often help you find others, for large n. For instance, if n=11, then {-11, -10, -7, -5} is one solution. But we could swap the -5 for any combination that adds to 5 that isn't in our set. Thus {-11, -10, -7, -3, -2} is also a solution, and similarly for -7, giving {-11, -10, -5, -4, -3} as a solution (we are not allowed to use -1 because the 1 must be positive). We could continue replacing the -10, the -11, and their components similarly to pick up six more solutions.
This is probably how I'd approach this problem. Use a greedy algorithm to find the "largest" solution (the solution using the largest possible numbers), then keep splitting the components of that solution into successively smaller solutions. It is again fundamentally a recursion problem, but one whose running time decreases with the size of the component under consideration and which at each step generates another solution if a "smaller" solution exists. That being said, if you want every solution then you still have to check non-greedy combinations of your split (otherwise you'd miss solutions like {-7, -4, -3} in your n=7 example). If you only wanted a lot of solutions it would definitely be faster; but to get all of them it may be no better than a brute-force approach.
If I were you I would go for a graph implementation, and DFS algorithm. Imagine you have N nodes that are representing your numbers. Each number is connected to another via an "add" edge, or a "subtract" edge. So you have a fully connected graph. You can start from a node and compute all dfs paths that lead to zero.
For more information about DFS algorithm, you can see the wikipage.
Edit: In order to clarify my solution, the graph you will end up having will be a multigraph, which means that it has more than one edge between nodes. DFS in a multigraph is slightly more complicated, but it is not that hard.
I would suggest a straight forward solution because as you mentioned you are dealing with consecutive integer from 1 to N which are fixed. The only things that vary are the operators in between.
Let's look at your example before we implement a general solution:
For n = 7 you need somehow to produce all possible combinations:
1+2+3+4+5+6+7
1+2+3+4+5+6-7
1+2+3+4+5-6+7
1+2+3+4+5-6-7
...
1-2-3-4-5-6+7
1-2-3-4-5-6-7
If we remove the numbers from above strings/expressions then we'll have:
++++++
+++++-
++++-+
++++--
...
----+-
-----+
------
Which reminds on binary numbers; if we interpret + as 0 and - as 1 the above can be mapped to the binary numbers from 000000 to 111111.
For an input n you'll have n-1 operators inbetween, which means the count of all possible combinations will be 2^n-1.
Putting all the above together something like below can be used to print those which sums are zero:
public static void main(String args[]) throws IOException{
permute(7);
}
public static void permute(int n){
int combinations = (int)Math.pow(2, n-1);
for(int i = 0; i < combinations; i++){
String operators =String.format("%"+(n-1)+"s", Integer.toBinaryString(i)).replace(' ', '0');
int totalSum = 1;
StringBuilder sb = new StringBuilder();
for(int x = 0; x< operators.length(); x++){
sb.append(x+1);
if(operators.charAt(x)=='0'){
sb.append("+");
totalSum = totalSum + (x+2);
}
else{
sb.append("-");
totalSum = totalSum-(x+2);
}
}
sb.append(n);
if(totalSum == 0){
System.out.println(sb.toString() + " = " + totalSum);
}
}
}
Note/Example: String.format("%6s", Integer.toBinaryString(13)).replace(' ', '0') will produce a string with length = 6 from the binary representation of 13 with leading zeros, i.e 001101 instead of 1101 so that we get the required length of the operators.
This is an interesting question. It involves more math than programming because only if you discover the math portion then you may implement an efficient algorithm.
However even before getting into the math we must actually understand what exactly the question is. The question can be rephrased as
Given array [1..n], find all possible two groups (2 subarrays) with equal sum.
So the rules;
sum of [1..n] is n*n(+1)/2
If n*(n+1)/2 is odd then there is no solution.
If your target sum is t then you should not iterate further for lower values than Math.ceil((Math.sqrt(8*t+1)-1)/2) (by solving n from n(n+1)/2 = t equation)
Sorry... I know the question requests Java code but I am not fluent in Java so the code below is in JavaScript. It's good though we can see the results. Also please feel free to edit my answer to include a Java version if you would like to transpile.
So here is the code;
function s2z(n){
function group(t,n){ // (t)arget (n)umber
var e = Math.ceil((Math.sqrt(8*t+1)-1)/2), // don't try after (e)nd
r = [], // (r)esult
d; // (d)ifference
while (n >= e){
d = t-n;
r = d ? r.concat(group(d, d < n ? d : n-1).map(s => s.concat(n)))
: [[n]];
n--;
}
return r;
}
var sum = n*(n+1)/2; // get the sum of series [1..n]
return sum & 1 ? "No solution..!" // if target is odd then no solution
: group(sum/2,n);
}
console.log(JSON.stringify(s2z(7)));
So the result should be [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]].
what does this mean..? If you look into that carefuly you will notice that
These are all the possible groups summing up to 14 (half of 28 which is the sum of [1..7].
The first group (at index 0) is complemented by the last group (at index length-1) The second is complemented with the second last and so on...
Now that we have the interim results it's up to us how to display them. This is a secondary and trivial concern. My choice is a simple one as follows.
var arr = [[1,6,7],[2,5,7],[3,4,7],[1,2,4,7],[3,5,6],[1,2,5,6],[1,3,4,6],[2,3,4,5]],
res = arr.reduce((r,s,i,a) => r+s.join("+")+"-"+a[a.length-1-i].join("-")+" = 0 \n","");
console.log(res);
Of course you may put the numbers in an order or might stop halfway preventing the second complements taking positive values while the firsts taking negative values.
This algorithm is not hard tested and i might have overlooked some edges but I believe that this should be a very efficient algorithm. I have calculated up to [1..28] in a very reasonable time resulting 2399784 uniques groups to be paired. The memory is only allocated for the constructed result set despite this is a resursive approach.
It is a good question, but first you must have to try to solve it and show us what you tried so we can help you in the solution, this way you will improve more effectively.
However, the below code is a solution I have write before years, I think the code need improvement but it will help..
public static void main(String[] args) {
String plus = " + ", minus = " - ";
Set<String> operations = new HashSet<>();
operations.add("1" + plus);
operations.add("1" + minus);
// n >= 3
int n = 7;
for (int i = 1; i < n - 1; i++) {
Set<String> newOperation = new HashSet<>();
for (String opt : operations) {
if ((i + 2) == n) {
newOperation.add(opt + (i + 1) + plus + n);
newOperation.add(opt + (i + 1) + minus + n);
} else {
newOperation.add(opt + (i + 1) + plus);
newOperation.add(opt + (i + 1) + minus);
}
}
operations.clear();
operations.addAll(newOperation);
}
evalOperations(operations);
}
private static void evalOperations(Set<String> operations) {
// from JDK1.6, you can use the built-in Javascript engine.
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
try {
for (String opt : operations) {
if ((int) engine.eval(opt) == 0) {
System.out.println(opt + " = 0");
}
}
} catch (ScriptException e) {
e.printStackTrace();
}
}
First, the question is the special case of sum to N.
Second, sum a list to N, could be devided to the first element plus sublist and minus sublist.
Third, if there are only one element in the list, check if n equals the element.
Fourth, make recursion.
Here's the scala implementation, try finishing your java version:
def nSum(nums: List[Int], n: Int, seq: String, res: ListBuffer[String]): Unit =
nums match {
case Nil => if (n == 0) res.append(seq)
case head :: tail => {
nSum(tail, n - head, seq + s" + $head", res)
nSum(tail, n + head, seq + s" - $head", res)
}
}
def zeroSum(nums: List[Int]): List[String] = {
val res = ListBuffer[String]()
nSum(nums.tail, -nums.head, s"${nums.head}", res)
res.map(_ + " = 0").toList
}
val expected = List(
"1 + 2 - 3 + 4 - 5 - 6 + 7 = 0",
"1 + 2 - 3 - 4 + 5 + 6 - 7 = 0",
"1 - 2 + 3 + 4 - 5 + 6 - 7 = 0",
"1 - 2 - 3 - 4 - 5 + 6 + 7 = 0")
assert(expected == zeroSum((1 to 7).toList))
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
For the following code segment, I am having trouble tracing through it (which I need to be able to do for my upcoming test.
public int question(int x, int y)
{
if (x ==y)
return 0;
else
return question(x-1, y) + 1;
}
I am also confused as to what the + 1 is doing. What is 1 being added on to. I know the result is five, but I need to be able to better understand the concept. Thanks for your help.
Basically:
question(8,3) will return question(7,3) + 1
question(7,3) will return question(6,3) + 1
question(6,3) will return question(5,3) + 1
question(5,3) will return question(4,3) + 1
question(4,3) will return question(3,3) + 1
and question(3,3) is 0.
It should be obvious that the result of question(8,3) is 5 by simple substitution. It should be noted that if x < y then you might get a stack overflow as x keeps decrementing and will possibly never get to x == y.
the 1 is being added onto the return from the function every time the function recurses 1 is added onto the return of int
public int question(int x, int y)
{
if (x ==y)
return 0;
else
return question(x-1, y) + 1;
}
say you call
int result = question(5,0);
since your general case calls
return question(x-1, y) + 1;
the + 1 is going to recurse until you hit the base case of
if (x ==y)
return 0;
giving you +1 +1 +1 +1 +1 +0
until x = 0 and y = 0
You can always add a couple prints to the method to better understand what it is doing:
static int question(int x, int y) {
if (x ==y) {
System.out.println(x + " == " + y);
System.out.println("return 0");
return 0;
} else {
System.out.println(x + " != " + y);
System.out.println("call question(" + (x - 1) + ", " + y + ")");
int result = question(x - 1, y);
System.out.println("return " + result + " + 1");
return result + 1;
}
}
Then call it. For example:
public static void main(String... args) {
System.out.println(question(8, 3));
}
Output:
8 != 3
call question(7, 3)
7 != 3
call question(6, 3)
6 != 3
call question(5, 3)
5 != 3
call question(4, 3)
4 != 3
call question(3, 3)
3 == 3
return 0
return 0 + 1
return 1 + 1
return 2 + 1
return 3 + 1
return 4 + 1
5
In order to understand recursion, try to write function in a mathematical way. I will first demonstrate this with the classic factorial, then explain you the example you gave.
Let fact(n) be n!. The recursive definition of factorial is:
fact(n) = 1, if n <= 1
fact(n) = n * fact(n - 1)
Note that we have 2 cases: a base case, which is a simple case that can be calculated directly, and a step case, which requires the value of a recursive call. Note that in order for the recursion to work, the recursive function call should be simpler, in order to move towards the step case. This can be implemented easily in Java:
public int factorial(int n)
{
if (n < 2)
return 1;
else
return n*factorial(n-1);
}
Returning to your function, you have to do the same process backwards. We can easily identify the 2 base cases as the branches of if:
Base case: question(x, y) = 0, if x = y
Step case: question(x, y) = question(x - 1, y) + 1, otherwise
It can be noticed that at each recursive call you subtract 1 from x and add 1 to the result. Let's unroll the recursion for question(8, 3):
question(8, 3) = question(7, 3) + 1 // You are in the step case
question(7, 3) = question(6, 3) + 1
question(6, 3) = question(5, 3) + 1
question(5, 3) = question(4, 3) + 1
question(4, 3) = question(3, 3) + 1
question(3, 3) = 0 // The base case
Now, if you replace the value of question(3, 3) in the value of question(4, 3) and do the same upwards, you find out that the result is 8.
There is no straight way to do this, but you can notice that the first parameter is decreasing by 1 and each time this is done, the result increases by 1, until the parameters are equal. Using some intuition, you may notice that this basically computes x - y.
Note that this method requires x >= y, otherwise it will crash.
I'm preparing for a java programming exam that's coming up in a few days and I've been tryna get my head around this:
The initial starting value of int num is 8
public int func1(int num)
{
if(num <=1) return 1;
return num + func1 (num - 3);
}
How do you go through through the return num + func1 (num - 3) part?
I don't get how that line of code works
I hope this will help you understand recursion.
return 8 + func1(5)
return 8 + 5 + func1(2)
return 8 + 5 + 2 + func1(-1)
return 8 + 5 + 2 + 1
and finally returns like
return 8 + 5 + 3
return 8 + 8
return 16
Easiest way to understand recursion is
Assume that the whole public int func1(int num) is inserted in the return
so ur function returns somewhat in this way
return 8 + func1((8) - 3) // i.e return 8 + func1(5)
return 8 + 5 + func1((5) - 3) // i.e return 8 + 5 + func1(2)
return 8 + 5 + 2 + func1((2) - 3) // i.e return 8 + 5 + 2 + func1(-1)
return 8 + 5 + 2 + 1
So total will be 16
Just trace through it the exact same as for any other method call. It's just calling itself which is another way to do a loop.
i.e.
func1(8)
calls func1(8-3)
calls func1(5-3)
calls func1(2-3)
returns 1 as -1 < 1
returns 2+1
returns 5+3
returns 8+8
So the final result is 16.
"The only way to understand recursion is to understand recursion".
Now seriously, you need to think of the execution of a recursive program as a stack with a basic case and a general case:
For instance the factorial method:
Basic case: f(n) = 1, if n = 0.
General case: f(n) = n*f(n-1), otherwise.
Result would be:
f(n) = n*f(n-1)
f(n-1) = (n-1)*f(n-2)
...
f(2) = 2*f(1)
f(1) = 1*f(0)
f(0) = 1
Basically you need to go down until the basic case and then reconstruc the result via the partial results you are finding.
Recursive algorithms are very useful for some methods which otherwise would require lots of memory to store intermediates value.