I'm new to recursion and don't understand how it works.
This was a classwork problem that had the answer 18, but I don't understand how. From what I know, this should return 6 + 5 + 4 + 3 (3 + m-1 on the recursive line)?
Are the subtraction signs not indicative of subtraction? (assuming that m = 5)
public int test(int m)
{
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
return value;
}
6 + 5 + 4 + 3 (3 + m-1 on the recursive line)? Are the subtraction
signs not indicative of subtraction?
No the +3 will happen for every one of the recursive calls, actually what your function is doing is given the value of (m times 3) + 3.
So for m=5 the recursive calls will be like:
Is m = 0 ? No so let us called recursively:
test(4) + 3
m = 4; then test(3) + 3 + 3
m = 3; then test(2) + 3 + 3 + 3
m = 2; then test(1) + 3 + 3 + 3 + 3
m = 1; then test(0) + 3 + 3 + 3 + 3 + 3
m = 0; then exit with 3 + 3 + 3 + 3 + 3 + 3
Hence, for m=5 you get 18.
A side-note you can use the ternary operator to simplify your method to:
static public int test(int m) {
return (m == 0) ? 3 : test(m - 1) + 3;
}
For visualizing what happens, scatter the code with messages:
public int test(int m)
{
System.out.println("entering test("+m+")");
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
System.out.println("returning "+value+" from test("+m+")");
return value;
}
Of course this is just the minimal program, you could also show which branch of the if was taken, m-1, and so on.
JavaScript equivalent, so it can run here in the browser:
function test(m) {
console.log("entering test(" + m + ")");
var value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
console.log("returning " + value + " from test(" + m + ")");
return value;
}
console.log("result: "+test(3));
On the longer run it is a good idea to learn using the debugger of the environment you are using. Among other things, debuggers can step through code line-by-line.
Related
import java.util.*;
public class Main {
public static void main (String[] args) {
Solution solution = new Solution();
int[] res = solution.assignTasks(new int[]{3,3,2}, new int[]{1,2,3,2,1,2});
}
}
class Solution {
public int[] assignTasks(int[] servers, int[] tasks) {
PriorityQueue<Pair> free = new PriorityQueue(); // (wt, id, time)
PriorityQueue<Pair> busy = new PriorityQueue(); // (time, wt, id)
for (int i = 0; i < servers.length; i++) {
free.add(new Pair(servers[i], i, 0));
System.out.println("Free Added " + i + " " + servers[i] + " " + i + " " + 0 + " " + free.size());
}
int[] ans = new int[tasks.length];
for (int i = 0; i < tasks.length; i++) {
Pair b = busy.peek();
while (b != null && b.a <= i) {
busy.poll();
System.out.println("Busy Polled " + i + " " + b.a + " " + b.b + " " + b.c + " " + busy.size());
free.add(new Pair(b.b, b.c, b.a));
System.out.println("Free Added " + i + " " + b.b + " " + b.c + " " + b.a + " " + free.size());
b = busy.peek();
}
Pair p = free.poll();
int wt = p.a;
int id = p.b;
// int time = p.c;
System.out.println("Free Polled " + i + " " + p.a + " " + p.b + " " + p.c + " " + free.size());
ans[i] = id;
busy.add(new Pair(i + tasks[i], wt, id));
System.out.println("Added to Busy " + i + " " + (i + tasks[i]) + " " + p.a + " " + p.b + " " + busy.size());
}
return ans;
}
}
class Pair implements Comparable<Pair> {
int a, b, c;
Pair(int x, int y, int z) {
a = x;
b = y;
c = z;
}
public int compareTo(Pair p) {
if (this.a == p.a) {
if (this.b == p.b) return this.c - p.c;
return this.b = p.b;
}
return this.a - p.a;
}
}
I have inserted triplets using Pair class in the priority queue and one pair is polled from the queue two times and was inserted only once. How it could be possible?
I am also attaching the console output for print statements I added to debug. Highlighted the unusual behavior.
The output of Code: (Note the behavior in output. Highlighting it (3,0,0) polled twice?)
Free Added 0 3 0 0 1 (Added to the queue)
Free Added 1 3 1 0 2
Free Added 2 2 2 0 3
Free Polled 0 2 2 0 2
Added to Busy 0 1 2 2 1
Busy Polled 1 1 2 2 0
Free Added 1 2 2 1 3
Free Polled 1 2 2 1 2
Added to Busy 1 3 2 2 1
Free Polled 2 3 0 0 1 (Polled 1st time)
Added to Busy 2 5 3 0 2
Busy Polled 3 3 2 2 1
Free Added 3 2 2 3 2
Free Polled 3 2 2 3 1
Added to Busy 3 5 2 2 2
Free Polled 4 3 0 0 0 (Polled 2nd time)
Added to Busy 4 5 3 0 3
Busy Polled 5 5 3 0 2
Free Added 5 3 0 5 1
Busy Polled 5 5 3 0 1
Free Added 5 3 0 5 2
Busy Polled 5 5 3 2 0
Free Added 5 3 2 5 3
Free Polled 5 3 0 5 2
Added to Busy 5 7 3 0 1
The question was from a recent Leetcode Contest that was over now. Link to the discussion section of the question. Link to question
Link to IDE run
It is not entirely clear, but I think your problem is caused by an incorrect implementation of compareTo.
public int compareTo(Pair p) {
if (this.a == p.a) {
if (this.b == p.b) return this.c - p.c;
return this.b = p.b;
}
return this.a - p.a;
}
Problem #1
return this.b = p.b;
This returns p.b and as a side-effect it assigns p.b to this.b. This is completely wrong.
It is possible that you mean return this.b - p.b;
Note that since your compareTo method is changing one of the Pair objects, the results are going to be messed up. That's probably why some of the Pair objects appear to be returned more than once. (In fact, they are different Pair objects ... but you have mutated them so that they have the same values in the c field.)
Problem #2
The expression this.c - p.c gives an incorrect answer in edge cases. For example, this.c is very large and p.c is negative, then the subtraction may overflow to a negative number which says that this.c is "less" than p.c ... which it isn't.
See Java Integer compareTo() - why use comparison vs. subtraction? for a more on this.
Here are a couple of correct ways to compare two int values to give a result that is compatible with the compareTo contract:
Longhand:
if (this.c == p.c) {
return 0;
} else if (this.c < p.c) {
return -1;
} else {
return +1;
}
Using conditional expressions:
return (this.c == p.c) ? 0 : ((this.c < p.c) ? -1 : +1);
Using Integer.compare
return Integer.compare(this.c, p.c);
Correct implementation
If we assume that the Pair objects are supposed to be immutable, then this is a correct1 implementation:
class Pair implements Comparable<Pair> {
final int a, b, c;
Pair(int x, int y, int z) {
a = x;
b = y;
c = z;
}
public int compareTo(Pair p) {
if (this.a == p.a) {
if (this.b == p.b) {
return Integer.compare(this.c, p.c);
} else {
return Integer.compare(this.b, p.b);
}
} else {
return Integer.compare(this.a, p.a);
}
}
}
Q: Why declare the fields as final ?
A: To prevent accidental changes to the fields, within the Pair class itself and also by other classes to which the class and its fields are accessible.
Q: Why use if ... else?
A: Because it is clearer. And because the JIT compiler should generate equivalent (optimal) code in either case.
Q: What about compare? Won't the method call be inefficient?
A: Probably not. The method call will probably be inlined by the JIT compiler.
Q: Does efficiency matter at all?
A: In your example it is irrelevant. In the general case, it is probably irrelevant2.
1 - The class name Pair is also incorrect. It should be Triple.
2 - You should only try to hand optimize this after you have 1) benchmarked your code, 2) profiled it, and 3) determined that the compareTo method is really a performance hotspot.
public static int wacky (int x , int y){
if(x <= 1){
return y;
}
else{
return wacky(x - 1, y - 1) + y;
}
}
I had a test a while but I still don't know how to do a recursion step by step and I remember this question by memory and I guess on the test thinking that you maybe calculate this way...
public static = 4 + 6 + 1 + 4 + 4 - 1 + 6 - 1 + 6
but was not of the answer choice I realize i was doing something wrong...
my teacher doesn't help me and don't even care I try to get help but he does not how to explain this...
When you call a function recursively, they add the new function to a stack until have a final result (return). When it occurs, you go back return by return in the stack.
An Execution example:
First Round wacky(4, 6):
4 <= 1? No, so call wacky(4 - 1, 6 - 1)
Second Round wacky(3, 5):
3 <= 1? No, so call wacky(3 - 1, 5 - 1)
Third Round wacky(2, 4):
2 <= 1? No, so call wacky(2 - 1, 4 - 1)
Fourth Round wacky(1, 3):
1 <= 1? Yes
return 3;
return 3 + 4;
return 3 + 4 + 5;
return 3 + 4 + 5 + 6;
Why not let Java tell you what is going on? Insert some print statements so you can see the values when the code runs:
private static int indent = 1;
public static int wacky(int x , int y) {
System.out.printf("%" + (indent++ * 2) + "swacky(%d, %d)%n", "", x, y);
int result;
if (x <= 1)
result = y;
else
result = wacky(x - 1, y - 1) + y;
System.out.printf("%" + (indent-- * 2) + "s-> %d%n", "", result);
return result;
}
Test
wacky(4, 6);
Output
wacky(4, 6)
wacky(3, 5)
wacky(2, 4)
wacky(1, 3)
-> 3
-> 7
-> 12
-> 18
I need to print the factors of a perfect number. Here's the gist of my main class:
ArrayList<Integer> perfNums = new ArrayList<>();
Scanner in = new Scanner(System.in);
System.out.print("Enter the upperbound: ");
upperbound = in.nextInt();
for (int i = 1; i <= upperbound; i++) {
if (isPerfect(i)) { //boolean to check if number is a perfect number
perfNums.add(i);
}
}
System.out.println("Perfect numbers between 1 and " + upperbound + " are:");
for (int i = 0; i < perfNums.size(); i++) {
System.out.print(perfNums.get(i) + " = ");
printFactor((int)perfNums.get(i));
System.out.println();
}
Here's the printFactor class.
private static void printFactor(int number){
int factor = 1;
while(factor < number){
if (number%factor == 0) System.out.print(factor+ " + ");
//I don't know how to print the + sign otherwise.
factor++;
}
}
And here's a sample output:
Enter the upperbound: 10000
Perfect numbers between 1 and 10000 are:
6 = 1 + 2 + 3 +
28 = 1 + 2 + 4 + 7 + 14 +
496 = 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248 +
8128 = 1 + 2 + 4 + 8 + 16 + 32 + 64 + 127 + 254 + 508 + 1016 + 2032 + 4064 +
I've got the main gist of it but I've struggled with an output issue. Due to the restrictions of my online submission system, my output needs to fit exact specifications.
My question is how do I go about printing all the factors of my perfect number but removing the + sign at the end? (e.g)6 = 1 + 2 + 3
I'm not too sure of many methods to print from a while loop. Would a for-loop be better for my goals? Or are there alternative methods to print the factors of a number?
The least amount of change to address this might be something like this:
private static void printFactor(int number)
System.out.print(1);
int factor = 2;
while (factor<number) {
if (number%factor == 0) System.out.print(" + " + factor);
factor++;
}
}
1 is always a factor, so you can print that before the loop and then prepend + to every subsequent factor.
You should cache the output you want to print into a StringBuilder. Then you are able to remove the last plus sign before you print the whole String. It also has a better performance.
private static void printFactor(int number)
{
StringBuilder output = new StringBuilder();
int factor = 1;
while (factor < number)
{
if (number % factor == 0)
output.append(factor + " + ");
factor++;
}
// remove last plus sign
output.deleteCharAt(output.length() - 1);
// print the whole string
System.out.print(output.toString());
}
Since factor starts from value 1 and number % 1 == 0 will always be true, you might print 1 first and then flip factor and + in System.out.print. Like this:
private static void printFactor(int number) {
if(number > 0) {
System.out.print(1);
}
int factor = 2;
while (factor<number) {
if (number % factor == 0) {
System.out.print(" + " + factor);
}
factor++;
}
}
Not the best solution, but it will do the job.
Try to create a variable String numb and use substring method like this:
String numb ="";
while(factor<number){
if(number%factor == 0)
numb= numb + factor+ " + ";
factor++;
}
System.out.print(numb.substring(0, numb.trim().length()-1));
Just for the sake of using Java 8 :)
private static void printFactor(int number){
System.out.println(IntStream.range(1, number)
.filter(p -> number % p == 0)
.mapToObj(i -> String.valueOf(i))
.collect(Collectors.joining(" + ")));
}
Thanks everyone for the quick response. You all have been a lifesaver, and I managed to pick up some new things to consider when I code in the future.
Anyway, while waiting for a reply I was fiddling with the code and came up with a rather inelegant solution, if anybody's interested. Here's the changes to the main class:
System.out.println("Perfect numbers between 1 and " + upperbound + " are:");
for(int i=0; i<perfNums.size(); i++){
System.out.print(perfNums.get(i) + " = ");
outputString = printFactor2(perfNums.get(i));
if(outStr.endsWith(" + ")) outStr = outStr.substring(0, outStr.length()-3);
//because the submission system would cry foul with even a single extra space
System.out.println(outStr);
}
And here's the changes to the printFactor class:
private static String printFactor2(int number){
String out = "";
int factor = 1;
while(factor<number){
if(number%factor == 0) out += factor + " + ";
factor++;
}
return out;
}
Basically, what I did was append the factors to a string, then removing the trailing + sign using the substring method. On hindsight, I probably should've called the substring method inside the printFactor class instead. Something like return out.substring(0, out.length()-3); perhaps?
Nevertheless, thanks everyone!
I am trying to understand this recursive method but even with a debugger I couldn't come up to something that makes sense to me so i hope someone here is motivated to explain me what is going on here. I know how recursion works basically but the way this method is written down troubles me.
I know the conditional operator in java and I worked out a new code but still I don't understand it, so what I expect here is.
What is the result for m(5) AND m(15). How did you calculate it? Thanks
Edit after the answers. I made a table with my results for future readers
m(n)::|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|...
result|0|0|1|1|1|2|3|4|6|9|13|19|28|41|60|88|...
I checked only the result of 15 with my program.
public class practice {
/**
* Try to understand the way this works
* #param n
* #return
*/
static long m(long n) {
return n <= 1 ? 0 : n == 2 ? 1 : m(n - 1) + m(n - 3);
}
/**
* This is what i tried so far.
* #param n
* #return
*/
static long ma(long n) {
System.out.println("Method called");
System.out.println("N is: " + n);
if (n <= 1) {
System.out.println("N<=1: " + n);
System.out.println("0 is returned");
return 0;
} else if (n == 2) {
System.out.println("N==2: " + n);
System.out.println("1 is returned");
return 1;
} else {
System.out.println("Inside ELSE, N is: " + n);
return ma(n - 1) + ma(n - 3);
}
}
public static void main(String[] args) {
ma(15);
}
}
Wrote it this way to make it more understandable:
m(0) = 0
m(1) = 0
m(2) = 1
m(n) = m(n - 1) + m(n - 3) // n >= 3
When we know the values for m(0), m(1) and m(2), we can calculate any m(n), where n >= 3, using m(n - 1) + m(n - 3). For any negative input, the result is 0.
For example:
m(3) = m(3 - 1) + m(3 - 3) = m(2) + m(0) = 1 + 0 = 1
m(4) = m(4 - 1) + m(4 - 3) = m(3) + m(1) = 1 + 0 = 1
m(5) = m(5 - 1) + m(5 - 3) = m(4) + m(2) = 1 + 1 = 2
And so on...
Pencil and paper are you friends.
There are 3 cases (two of them are base conditions)
if n <= 1 then return 0
if n == 2 then return 1
else recursive call to m(n-1) + m(n-3)
So you know that on every recursive call we are approaching one of the base conditions.
Here is a stack trace of what happens on m(5)
m(5)
m(4) + m(2)
m(3) + m(1) return 1
m(2) + m(0) return 0
return 1 return 0
Adding all the returns gives 1 + 0 + 0 + 1 which is 2
So
m(5) == 2
Method m in pseudo code. (this is some kind of scala/python mash up)
def m (number n)
if (n <= 1) 0
else if (n == 2) 1
else m(n - 1) + m(n - 3)
Looking at this you can see that anything <= 2 is a terminal operation, returning 0 or 1 based on the input. If n is > 2, the fun begins. Take for example n=3. Since 3 is greater than 2, we need to run the third if. When we look at that line we see that we nee to return m(n - 1) + m(n - 3). Plugging n = 3 in, it looks like this: m(3 - 1) + m(3 - 3), or, more simplified, like this: m(2) + m(0). This will now terminate with 1 because neither 2 or 0 for n will result in more calling of m.
So now we have something we understand we can now workout what m(15) and m(5) will return.
I will only work it out for 5 since the call stack for 15 would be way to long
m(5)
/ \
m(5-1) + m(5-3)
/ \ |
m(4-1) + m(4-3) |
/ \ | |
m(3-1) + m(3-3) | |
| | | |
1 + 0 + 0 + 1
2
Hope it helps!
m(5) = m(4)+m(2) // 5>2, so the third condition
m(4) + m(2) = m(3)+m(1) + 1 // 4>2, so the third condition
m(3) + m(1) + 1 = m(2)+m(0) + 0 + 1 // 3>2, so the third condition
m(2) + m(0) + 0 + 1 = 1 + 0 + 0 + 1 = 2
Now, between transformations, m(2) s instantly replaced with 1, and m(n<=1) is instantly replaced with 0. This is how you can analyze this on paper. Computer, however, would wirst calculate m(4) before calculating m(2) and adding the results in the first line - this happens because of order of poerations within the recursive functions.
I am trying to write a function using which I can obtain any natural number in minimum steps. Where I am allowed to add or subtract natural numbers starting from 1.
There the conditions are :
Use a number only once
You are allowed to perform only addition and subtraction.
You are not allowed to escape any digit
Find the value of the integer which has a maximum value to obtain that number.
eg : If I my desired number is 4 then it is obtained as -1+2+3 here answer is 3. In a similar manner if I want 6 then 1+2+3 here answer is 3. For 10= 1+2+3+4 ans is 4.
what I have so far :
What I have so far:
public void step() {
int n = (int)Math.sqrt(position * 2);
k = (position - (((n + 1) * n) / 2));
l = ((((n + 1) * (n + 2)) / 2) - position);
System.out.println(k + " " + l);
System.out.println(n);
p = (l > k ? k : l);
r = (l > k ? n : n + 1);
System.out.println(p + " " + r);
if (k == 0) {
result = n;
} else {
result = r + (2 * p);
} System.out.println("__________" + result + "__________");
}
Ok, lets do it in this way. Consider following binary tree. now you can find sum from each path and take every path with sum=your number(let's say 4). now you can get the maximum value from those. Try to come up with implementation of this. I can help you further, If you try some thing.
0
/ \
-1 1
/ \ / \
-2 2 -2 2
The solution is :
for n=1: = 1
for n=2: = 1+2 => 1+2+3 => 1-2+3
for n=3: = 1+2
for n=4: = 1+2+3 => -1+2+3
for n=5: = 1+2+3 => 1+2+3+4-5
for n=6: = 1+2+3
for n=7: = 1+2+3+4=>1+2+3+4+5=>1+2+3-4+5
for any n, first calculate the S(k)=1+2+3+...+k
where S(k)>n and x=S(k)-n is an even number. Then go flip the + of x/2 to -.
S(k) = (1+k)*k/2 > n
=> k*k + k -2n > 0
=> k > (-1 + sqrt(1+8n))/2
eg, n=7, k > 3.2, then k=4, S(4) = 10, 10-7=3, it's odd, so k=5, S(5)=15, x=15-7=8, 8/2=4, flip the sign of 4, we got 1+2+3-4+5 = 7
in some cases, Sk-n is odd, but S(k+1)-n is also odd, in this case, we need to use S(k+2).
The code is as follow :
public void step() {
k = (int)Math.ceil(((-1 + Math.sqrt(1 + 8 * n)) / 2));
int Sk = (1 + k) * k / 2;
if ((Sk - n) % 2 != 0) {
k++;
Sk = (1 + k) * k / 2;
if ((Sk - n) % 2 != 0) {
k++;
Sk = (1 + k) * k / 2;
}
}
int i = (Sk - n) / 2;
System.out.println("maximum number is : " + k + "the number with -ve sign is : " + i);
}