I have to code a recursive method that iterates through a linked list and returns the number of integers that are positive. Here is the question:
The method countPos below must be a recursive method that takes a Node head
as its argument, goes down the list headed by head, and counts the number of nodes which have a positive data field.
The code I have works however, I don't understand how it works.
public int countPos(Node head) {
int count = 0;
if (head == null) { return count; }
if (head.data > 0) {
count++;
return count + countPos(head.next);
} else {
return count + countPos(head.next);
}
}
The problem I'm having is I don't understand how count doesn't get set back to 0 every time the method is called. For some reason the statement int count = 0; is ignored the next time the method gets called. Is this because I'm returning count also? Any explanation would be greatly appreciated.
Thanks.
DON'T begin by tracing execution or debugging. The power of recursion is that it lets you reason about complicated programs with simple logic.
Your code works by chance. It reflects that whoever wrote it (you?) doesn't understand how recursion solves problems. It's more complex than necessary.
To exploit recursion, take the problem at hand and:
Define the function interface.
Split the problem into parts, at least one of which is a smaller version of the same problem.
Solve that (or those) smaller version(s) by calling the function interface itself.
Find the "base case" or cases that are solutions to very small instances of the same problem.
With all this done, the pseudocode for most recursive algorithms is:
function foo(args)
if args describe a base case
return the base case answer.
solve the smaller problem or problems by calling foo with
args that describe the smaller problem!
use the smaller problem solution(s) to get the answer for this set of args
return that answer
end
Let's apply this to your case:
PROBLEM: Count the number of positive items in a list.
Define the function interface: int countPos(Node head).
Split the problem up into parts: Get the number of positives in the list remaining after the head, then add one if the head is positive and nothing if the head is zero or negative.
The smaller version of the problem is finding the number of positives in the list with head removed: countPos(head.next).
Find the base case: The empty list has zero positives.
Put this all together:
int countPos(Node head) {
// Take care of the base case first.
if (head == null) return 0;
// Solve the smaller problem.
int positiveCountWithoutHead = countPos(head.next);
// Now the logic in step 2. Return either the positive count or 1+ the positive count:
return head.data > 0 ? positiveCountWithoutHead + 1 : positiveCountWithoutHead;
}
You might learn a little bit by tracing execution of something like this one time. But trying to write recursive code by reasoning about what's going on with the stack is a dead end. To be successful, you must think at a higher level.
Let's try one that doesn't quite follow the standard template: Recursive binary search. We have an array a of integers and are trying to find the index of x if it exists in the array and return -1 if not.
PROBLEM: Search the array between positions i0 and i1-1.
(The above is an example of how you must sometimes "specialize" the problem by adding parameters so that smaller subproblems can be described in the recursive call or calls. Here we are adding the new parameters i0 and i1 so that we can specify a subarray of a. Knowing how and when to do this is a matter of practice. The parameters needed can vary with language features.)
Function interface: int search(int [] a, int x, int i0, int i1)
Split the problem in parts: We'll pick a "middle" element index: mid = (i0 + i1) / 2. Then the subproblem is either searching the first half of the array up to but excluding mid or the second half of the array starting after mid and continuing to the end.
The calls are search(a, x, i0, mid) and search(a, x, mid + 1, i1).
The base cases are that 1) if i0 >= i1, there are no elements to search, so return -1 and 2) if we have a[mid] == x, then we've found x and can return mid.
Putting this all together
int search(int [] a, int x, int i0, int i1) {
// Take care of one base case.
if (i0 >= i1) return -1;
// Set up mid and take care of the other base case.
int mid = (i0 + i1) / 2;
if (a[mid] == x) return mid;
// Solve one or the other subproblems. They're both smaller!
return x < a[mid] ? search(a, x, i0, mid) : search(a, x, mid + 1, i1);
}
And to start the search:
int search(int [] a, int x) { return search(a, x, 0, a.length); }
Each time you call countPos(), a new version of that function starts. This function starts from a clean slate meaning all of the local variables (count) are its own, and no other "copy" of countPos can see or modify its local variables.
The only state that is passed between these "copies" or of countPos is the variables that are passed in as parameters (Node head).
So here's a rough workflow assuming the list [1, -2, 3]
countPos starts, and says number of positive nodes is equal to 1, since "1" is positive. The total number of positive nodes is equal to 1 + whatever the next function returns.
The next function says the number of positive nodes is equal to 0 + whatever the next function returns.
The next function says the number of positive nodes is equal to 1 + whatever the next function returns
The next function sees that head == null and so returns 0.
Now each recursive function returns one after another to the original function that called it, with the total number of positive nodes "snowballing" as we return.
The total number returned in the end will be 2.
Related
I'm strugling learning recursive methods. Could use some advice and a cheer-up :D
Lets say I have a set of numbers in an array, and I want to use a recursive method to evaluate numbers in this set, and by evaluation I mean that our program needs to find zeros in this set, and as a result it should print out position of the last zero in given array.
int a[] = {2,3,4,5,0,1,2,0,5,0};
In case if array above is being evaluated by a recursive method, the program will evaluate each number and, if zero is found, it will save it's position in a variable, AND THEN MOVE ON REPEATING ITSELF until the end of the array. So first zero is at "4" and so on, but the output will show only the poistion number of the last zero in given array.
I kind of got the first part of this code going, but my recursion stops as soon as it finds a zero and just gives out a boolean type variable.
public static boolean checkNum(int i) {
if (i < a.length) {
if (a[i] != 0)
return checkNum(i+1);
else return false;
}
return true;
}
this block of code checks numbers in our set and returns boolean type variable true in case if it never found any zeros.
next method may be similar, but I dont know how to store the position number as a variable with a possibility to print it out in the end of my program. Is there any way to get int i out of the recursive method when it's done repeating itself? Because as far as I understand it is the same as a position number in an array, which I need to print out.
You have two options. Either continue until the end of the list and then return the last index found ... or iterate backwards across your list and use your logic as-is.
You're currently iterating forward, so might as well cover that workflow first.
Since your goal is to figure out the position, your method needs to return an int, not a boolean.
Since you need to return the last index of a zero, that means you need to track the previously found index.
Since you want to iterate to the end of the list, your end condition needs to be a position < length check.
static int[] a; // some array we're checking
public static int checkNum(int index, int lastZero) {
// End condition. If we've finished iterating across the array, return the
// index of the last zero we found.
if (index >= a.length) {
return lastZero;
}
// Check if we've found a zero at the current position.
if (a[index] == 0) {
lastZero = index;
}
// Continue traversing the list.
return checkNum(index+1, lastZero);
}
You'd call this by passing in a negative number as your initial lastZero index:
int lastZeroIndex = checkNum(0, -1);
That way you know that if you end up with a positive number, you have found the last index. Otherwise if you're left with a negative number, there were no zeroes in the array.
A simpler method would simply be to iterate backwards over the array and stop as soon as you find a zero.
We still return an int instead of a boolean because we want to know the index.
Otherwise your method signature remains the same.
static int[] a; // some array we're checking
public static int checkNum(int index) {
// End condition. We've reached the beginning of the array and never found a zero.
// Return a -1 to indicate this.
if (index < 0) {
return -1;
}
// If index is >= a.length, we don't want an index out of bounds...
if (index >= a.length) {
return checkNum(a.length - 1);
}
// Check if we've found a zero at the current position. If we have, return
// the current index.
if (a[index] == 0) {
return index;
}
// Continue traversing the list backwards.
return checkNum(index-1);
}
You'd call this by passing a.length - 1 as your parameter. That's the last valid index in the array, so it's our starting point when we iterate backwards.
int lastZeroFound = checkNum(a.length - 1);
If lastZeroFound is negative (eg. -1), then you found no zeroes.
I'm doing leetcode, and got in this confusion since the result of depth++ and depth+1 is totally different! I thought they were the same before. Can anyone explain the difference between them?
private void dfs(TreeNode root, List<Integer> res, int depth) {
if (root == null) return;
if (res.size() == depth) {
res.add(root.val);
}
dfs(root.right, res, depth + 1); // depth++ would get different result
dfs(root.left, res, depth + 1);
}
depth++ is the same as depth=depth+1 . The increment operator will modify and returns the copy of old depth.
int x = depth;
depth = depth+1;
return x;
depth+1 operation will return the value of expression without any modification.
return depth+1;
if you are using post increment with assignment
int a=1;
a = a++;
You can think this way (a=a++ => a=a and then a++)
Now when we assign [a=a++] a = 1 during assignment and after assignment a=2
if you are using post increment without assignment
int x=1;
x++;
Now x = 2 during assignment and x=2 after assignment also
The post increment operator varName++ uses the current value, then increments the variable, then continues executing the rest of the statement.
If you used the pre increment operator ++varName, the first call would work as it does with depth + 1, but would leave the variable incremented, requiring the next usage of it to factor this in:
dfs(root.right, res, ++depth); // increment before using value
dfs(root.left, res, depth); // depth already incremented
Although this would execute a very tiny amount faster due to avoiding 1 arithmetic operation, the code is harder to read and could lead to bugs if more code was added that did not expect depth to change within the method.
Some consider changing the value of method parameters poor style, although this style guideline is not universally accepted as best practice.
depth + 1 and depth++ are the same as result, but the way they are performed is different.
depth = depth + 1 applies the calculation results to the next operation.
depth++ First, performs an operation to the pre-addition value and then adds one.
I'm trying to teach myself coding, and I stumbled on an example I don't understand. Could someone give me an overview of what this code is supposed to do? I'm a bit confused about int a[] and what is later int a[i]. I know what an array is, but could someone please explain how this is being used in this context? Thank you in advance.
public class all {
public int select(int a[],int n,int x)
{
int i=0;
while(i<n && a[i]<x)
{
if(a[i]<0)
a[i]=-a[i];
i++;
}
return(a[i-1]);
}
}
This
if(a[i]<0)
a[i]=-a[i];
i++;
is he same like this
if(a[i]<0) {
a[i]=-a[i];
}
i++;
a[i] -> value at the position i, into the Array
if(a[i]<0) { -> if the value at position i is smaller than 0, also negative number
a[i]=-a[i]; -> replace the value with a reverse sign.
i++ -> increment loop Counter
Also what is done here: negative numbers convert to positive numbers.
while(i<n && a[i]<x) -> i = loop counter; if i smaller n and the value at position i in the array is smaller than x, then go into the loop.
return(a[i-1]); -> return the last value, that has been checked into the while loop
the method gets an array and two int args n and x (as a side note, I must say the names leave a lot to be desired...)
anyway, lets see what are the args for. they both are used in the while loop. the condition i<n tells us that n serves as upper limit to the iteration, while the condition a[i]<x tells us that x is used as upper limit to the values in the array.
so far, we can say:
select method receives an array, int arg specifying iteration-upper-limit and int arg specifying cell-value-upper-limit.
iterate over the array until you reach position specified by iteration-upper-limit or you reach a cell value that exceeds cell-value-upper-limit (which ever comes first)
can you continue to say what's being done inside the loop? it's fairly straightforward.
1.) a[] is the declaration of array.size is not defined.
2.)In a[i], i is the index number of the array...that means indicating the position of the element in array.
a[] is an array and we do not know its length. n must be lower than the length of a[] or it will throw an exception. It it traverses from the first element toward the last untill it one element is larger than x. it returns these element's absolute value which were traversed
The rules are that I have to return the largest number, so pretty much the user wants to find the biggest number. Split the array in half or close to it and find the biggest value from the array in the lower half and find the biggest value in the high half. I just started learning recursion and this problem is giving me nightmares.
public static double getBiggest(double[] a, int low, int high)
{
int mid = (low+high)/2;
double one = 0;
double two = 0;
if(a == null || a.length == 0 || low > high)
throw new IllegalArgumentException();
//How do I loop to find the biggest?
//A way to narrow down a big number of array values into a single one
one = getBiggest(a,low,mid);
two = getBiggest(a,mid,high);
if(one >= two)
return one;
else
return two;
return -1;
}
Your code is already pretty close, but since getBiggest always calls getBiggest(), it will never stop.
Before the recursive call, do something like this
if (low >= high)
{
return a[low];
}
That still leaves a little problem: When high == low+1, mid == low, so getBiggest(a,mid,high) will be the same size as the call you're in. Recursing with the same arguments again means that it will never stop.
Your recursive calls should be like:
one = getBiggest(a,low,mid);
two = getBiggest(a,mid+1,high);
That way both of the recursive calls are guaranteed to be smaller.
Finally, the conditional part at the end works, but the return a[mid] never happens. You should rewrite it like:
if(one >= two)
return one;
else
return two;
In English, the algorithm works like this:
If there's only one element, return it. Otherwise;
Get the biggest element in the first half (the first recursive call), then
Get the biggest element in the second half (the second recursive call), then
return whichever is bigger.
A recursive solution to a problem is made from solutions to smaller versions of the same problem.
Any recursive algorithm must ALWAYS have a base case - if the problem is small enough that it can be solved trivially then that must be done instead. The function must not invariably call itself recursively, otherwise you are guaranteed to get infinite recursion, which in Java means a StackOverflowException. In this case you always call getBiggest as long as the arguments are valid so that is your problem. You wrote "If the low to high section is 3 or bigger" but there is no such if statement in your code. Adding one will allow you to avoid recursion when low and high meet.
Your implementation has two problems:
It is not doing the arguments checking correctly - the check needs to happen at the top, and
You are missing the base case. Any recursive program must specify what to do when you are down to one or two items; your program is not doing it.
You need to add a condition at the top to see if high minus low is two or less. If it is one, return the number at the low end; if there are two numbers, pick the max and return it.
Can someone please explain how the recursion works.I tried to figure out writing down low,mid,high at each recursive call.But I seem to be making a mistake somehow.Can some one please show me the steps.Also I don't understand where the values are returned to in
if(leftmax>rightmax){
return leftmax;
}
else
return rightmax;
Here's the code:
public class Maximum{
public static int max(int[] a,int low,int high){
int mid,leftmax,rightmax;
if(low==high)
return a[low];
else{
mid=(low+high)/2;
leftmax=max(a,low,mid);
rightmax=max(a,mid+1,high);
if(leftmax>rightmax){
return leftmax;}
else
return rightmax;
}
}
public static void main (String args[]){
int[] a={32,8,12};
System.out.println(max(a,0,2));
}
}
So it appears this is the famous Divide and Conquer algorithm for finding an element, in this case, the maximum element.
The method starts with this input:
max(int[] a, int low, int hight)
a[] = { 32, 8, 12 }; //The target array. You want to find the maximum element in it.
low = 0; //The index of the array where you will start searching
high = 2; //The index of the array where you will stop searching
So, basically, low and high defines a "range", you will search the maximum elment within this range, if you want to search the whole array, then you specify the range to be the index 0 and the maximum possible index, that is the length of the array - 1 (Remember, index begins from zero, so you need to substract the offset)
The first condition in the method checks wether you gave a range with one element. In this case, low and high will be the same, becasue they refer to the same index on the array. Therefore, you just return that particular element in the index (You don't have to do any searching, if you are searching the maximum element in a one-element range, then the maximum element is that single element). Returning a[low] or a[high] is the same.
If you gave a range with more than one element, you go into the else section.
Here, you get the middle index of the range.
So, if you specified a range from index 3 (low), to index 7 (high), then the middle index would be 5. (* (low + high) / 2 *)
You then partition the range into two ranges, the left range and the right range, they both come from the same original range which was splitted by two.
You then perform all the above operations I stated with each of those two ranges, until, at same point, you will split so many ranges, that you will end up with a one-element range, and would return it.
Let's stop here for a second.
Look at the code, we are storing the return values of the splitted ranges in leftmax and rightmax accordingly, but since you are calling the same method, each splitted range will also have it's own leftmax and rightmax and it's own splitted ranges.
It's like you are diving deeper and deeper, the surface being the initial execution of the method.
The last level of deepness is giving a one-element range (result of a previous split). In this case, the method will stop calling itself, because it will actually return a value. Who will catch this returned value? The previous level, which can be very deep also, this deep level will capture the return values of the last level and do the comparition in the code, that is returning the max element, and will return the max element of these two numbers to the level above it, which will do the same, and return it to a higher level, and on and on and on, until you reach the surface level, with the two maximum numbers of each splitted array accordingly, you then check the maximum of these two numbers and return them to you (You are the highest level!).
I hope I explained the whole process clearly and helped you!!
1 low=0 high=2 mid=1
2 low=0 high=1 mid=0
3 low=0 high=0 --> return a[0] --> leftmax == 32
4 low=1 high=1 --> return a[1] --> rightmax == 8
leftmax > rightmax --> return leftmax == 32
5 low=2 high=2 --> return a[2] --> rightmax == 12
leftmax > rightmax --> return leftmax == 32
The max() function's job is:
If low and high are equal, return the value pointed to by the index
Otherwise, partition the section of the array we're looking at into two segments and call max() recursively on both halves. Then return the larger of the values returned by the two calls.