What is wrong with this method ? it seems but I am not sure that the comparison of adjacent children in the tree does not take place.
I roughly traced the workings of this algorithm by hand and I think the idea is correct maybe something wrong with the implementation or I have no Idea how recursion works, the second helper (compare) method seems to be the issue
public static int MAX(BST B) {
int m = ((Integer) B.root.data).intValue();
return call(B.root, m);
}
public static int call(node current, int max) {
//first helper method gets the max from two different levels in the tree
if(current == null)
return -1;
if(current.left == null && current.right == null)
return max;
else {
if(((Integer) current.data).intValue()>max)
max = ((Integer) current.data).intValue();
return compare(call(current.left,max),call(current.right,max));
}
}
//second helper method gets the max
static int compare(int m1, int m2) {
if(m1>m2)
return m1;
else
return m2;
}
Since you are searching the entire tree, I'm going to assume that the structure is not properly ordered.
The bug is in your call function with:
if(current.left==null&¤t.right==null) return max;
Imagine you have a tree with a root with two leaf nodes (three nodes total). The root has value 3, right has value 2, and left has value 5. The algorithm should return 5, but your code will return 3. This is because you ignore the value of any leaf (a node with no "children") with that line of code. So your code ignores the value 5, in this example, and returns max, which is 3.
You can fix this by returning compare(current.value, max) when left and right are null.
I think (not 100%) that you may have an issue because you only check if BOTH children are null if for example right is null and left is not you will attempt to call the method call on both right and. Perhaps add a case checking if one child is null and if so return call of the non null child.
... I have no Idea how recursion works ...
Recursion means the method you are in gets called from inside itself with some other arguments , and there is some check that exits by returning a value or continues to call itself recursively.
call() is indirectly recursive, as it either exits with a return of -1 or max or it calls itself again with new arguments and continues to do this until it either exits or crashes with an OutOfMemory error as the stack fills up.
This method isn't recursive: It is poorly named though.
static int compare(int m1, int m2) {
if(m1>m2)
return m1;
else
return m2;
}
and could be written ( and renamed ) as
static int min(final int m1, final int m2)
{
return Math.min(m1,m2);
}
or just inlined into
return Math.min(call(current.left,max),call(current.right,max));
either way, you are getting the minimum of the two values, not really comparing them that implies different logic and a different return value.
Either way that method isn't recursive and if the logic of m1 > m2 is appropriate it can't be the problem, more like the input to that function is not what you expect.
Step debugging is a powerful tool and one all experienced developers use every day!
Related
The code identifies the integer that is closest to 0 in an array and if there are 2 or more values that meet this condition the return value should be null.The problem is that when I make the condition to return null it displays an error because the function is supposed to return an integer.
static int function(int [] arr){
int closest=arr[0];
for(int i=1;i<arr.length;i++){
if(Math.abs(arr[i])<closest){
arr[i]=closest;
}
else if(arr[i]==closest){
return null;
}
}
return closest;
}
I am very new to Java (learned Python before),if there is a better/more eficient approach to this code please share.
You can convert the return type to Integer which can hold null and will auto box and unbox to an int:
static Integer function(int [] arr){
int closest=arr[0];
for(int i=1;i<arr.length;i++){
if(Math.abs(arr[i])<closest){
arr[i]=closest;
}
else if(arr[i]==closest){
return null;
}
}
return closest;
}
However this is probably not the best solution. You could instead return Integer.MAX_VALUE to signify that two of the elements were equidistant from zero. This depends on how you plan to handle the case where there are two elements of equal distance to 0.
If you need to support null (e.g. Python's None) then you should return the wrapper type Integer.
static Integer function(int [] arr) {
// ...
}
The obvious answer is to return Integer instead of int.
static Integer function(int[] arr) {
Autoboxing will take care of wrapping the primitive; autounboxing will take care of giving your client code NullPointerException.
But you said efficient, but allocating a genuine object is not efficient (small values will use a common object, but that still isn't great). Throwing an exception would be even less efficient (supposing it happens frequently enough.)
The routine could perhaps return any int value and we want to shove in an extra possible outcode. So one possibility is to go one larger and return a long with Long.MIN_VALUE as the special value. May require casting on the client code to get back to an int.
static Integer function(int[] arr) {
Long.MIN_VALUE is interesting in that Long.MIN_VALUE == Math.abs(Long.MIN_VALUE).
It's at this point we realise there's appears to be a bug in the code (not sure as I really know what it is supposed to be doing).
if(Math.abs(arr[i])<closest){
This is always true for Integer.MIN_VALUE. Probably you want to swap that around with.
if (-Math.abs(arr[i]) > -closest){
Converting to long before doing the comparison is also possible but less clever. (Integer overflows - bleurgh.)
Another way around the problem is to let the client code choose an appropriate value to signal the same as whatever null is supposed to indicate.
static int function(int[] arr, int dflt) {
[...]
} else if (arr[i] == closest) {
return dflt;
[...]
I need to write a Java method called findMax within a class called Node, which has two instance variables: int value and Node next. The method takes no parameters, and must return the greatest value of a linked list. Within the context of the program, the method will always be called by the first Node of a linked list (except for the recursive calls). I was struggling to complete the method when I accidentally found a working solution:
public int findMax(){
int max = value;
if(next == null){
return max;
}
else{
if(max <= next.findMax()){
max = next.value;
}
else return max;
}
return next.findMax();
}
This method properly returned the largest value of each linked list I tested it for. However, since I found this solution by trying random arrangements of code, I don't really feel like I understand what's going on here. Can anyone explain to me how/why this works? Also, if there is a more efficient solution, how would it be implemented?
You can imagine a linked list looking something like this:
val1 -> val2 -> val3 -> null
Recursion works on the principle that eventually, the input you pass into the function can be handled without recursing further. In your case, node.findMax() can be handled if the next pointer is null. That is, the max of a linked list of size 1 is simply the value (base case of the recursion), the max of any other linked list is the max of the value of that node or the max of the remaining elements.
ie) for the Node n3 with value val3, n3.findMax() simply returns the value
For any other node n, n.findMax() returns the maximum of the node's value or n.next.findMax()
The way this looks in the example at the start is:
n1.findMax()
= Max(n1.value, n2.findMax())
= Max(val1, Max(n2.value, n3.findMax())
= Max(val1, Max(val2, n3.value)) // Since n3.next == null
= Max(val1, Max(val2, val3))
which is simply the maximum over the whole list
Edit: Based on the discussion above, although what you said might work, there is a simpler way of writing the program:
int findMax() {
if (this.next == null) {
return this.value;
} else {
return Math.max(this.value, this.next.findMax());
}
}
Edit 2: A break down of why your code works (and why it's bad):
public int findMax(){
// This variable doesn't serve much purpose
int max = value;
if(next == null){
return max;
}
else{
// This if condition simply prevents us from following
// the else block below but the stuff inside does nothing.
if(max <= next.findMax()){
// max is never used again if you are here.
max = next.value;
}
else return max;
}
// We now compute findMax() again, leading to serious inefficiency
return next.findMax();
}
Why is this inefficient? Because each call to findMax() on a node makes two subsequent calls to findMax() on the next node. Each of those calls will generate two more calls, etc.
The way to fix this up is by storing the result of next.findMax() like so:
public int findMax() {
if (next == null) {
return value;
}
else {
int maxOfRest = next.findMax();
if(value <= maxOfRest) {
return maxOfRest;
}
else return value;
}
}
In the book, Cracking the Coding Interview (6th Edition), a problem asks me to:
Implement an algorithm to find the the kth to last element of a singly linked list
And later, the author claims:
Unfortunately, we can't pass back a node and a counter using normal return statements.
She is referring to the Java language in the above statement. She later on shows that we can only print the kth to last element in singly linked list in Java.
My question is this: Why can't we pass back a node when the recursion is popping frames? Why can't we add another argument to the recursive function such that that argument is set at the right time (i.e. when index = kth item) to the node we are looking for? I have been thinking about this since last night, and I just can't wrap my head around it.
The example answer provided looks like this:
int printKthToLast (LinkedListNode head, int k) {
if(head == null) {
return 0;
}
int index = printKthToLast(head.next, k) + 1;
if (index == k) {
System.out.println(k + "th to last node is " + head.data);
}
return index;
}
You are right when you say that we can "add another argument to the recursive function such that the argument is set at the right time". For example, this function works in the same way as the solution you posted:
private void printKthToLast(LinkedListNode head, int k, int index) {
if(head == null) {
return;
}
if(index >= k) {
System.out.println(head.data);
}
printKthToLast(head.next, k, ++index);
}
My guess is that the author was trying to illustrate that recursion typically "divides a problem into sub-problems, solves these sub-problems, and combines the results" (that is, the classic divide-and-conquer method). In this case, the division of problems into sub-problems is carried out when we call the recursive function on the "next" element, because we are getting closer to the base case (head == null). The results to combine is the index, which must be recursively incremented to determine when a node must be printed. This is why the index establishes the return type of the function (int). This is the correct way to solve the problem recursively. What you suggest is a possibility, but passing "index" as a parameter is neither division of problems into sub-problems nor combining the results.
In addition, it is also important to consider that, in Java, methods are not only identified by their names, but also by their input parameters, return types, etc. So, these two methods ...
private int printKthToLast(LinkedListNode head, int k)
private void printKthToLast(LinkedListNode head, int k, int index)
... are entirely distinct, even though they have the same name (this is called polymorphism). Therefore, including these two methods in the same solution would not be recursion.
LinkedListNode is used internally by the LinkedList.
There are no public methods on a LinkedList that allow to retrieve the internal LinkedListNode (actually called Entry).
Therefore, given a LinkedList, you cannot get access to the internal node.
Yet, if it is just to go through the list, you can simply use an iterator and recurse over it:
int printKthToLast (Iterator<E> it, int i) {
if(!it.hasNext()) {
return 0;
}
E e = it.next();
// ...
}
I have the following recursive method in a class called ImageNode which is passed the head(this - the start of the linked list) from a class called Image.
I thought my code would recursively go through each node, increase the count then when its at the end return the count, unfortunatly not. Where am I going wrong?
private int countRec() {
int count = 1;
ImageNode node = this;
if (node.next != null ){
node = node.next;
count++;
countRec();
}
return count;
}
You're ignoring the result of countRec() - and you're iterating within the recursive call, defeating the purpose. (You're also making a recursive call on the same object, with no parameters and no change in state... so that can't do any good.) My recursive approach would be based on a design of:
If the next node is null, then the size of the list is 1
Otherwise, the size is 1 + the size from the next node onwards.
So:
private int countRec() {
return next == null ? 1 : 1 + next.countRec();
}
Now that doesn't allow for a list of length 0 of course... you probably want to separate the idea of the list from the node, in which case the list class would have something like:
public int count() {
return head == null ? 0 : head.countRec();
}
where the value of head is a reference to the head node if there is one, or null otherwise.
Of course, this will be O(n) in time and space. You can get O(1) space using iteration instead of recursion, and O(1) time by just keeping the size of the list as an instance variable in the list, updating it when you need to. I'm hoping that this question was based on an educational requirement rather than real code though - in production code, you'd just use the collections provided already.
The definition of a recursive function is it is defined in terms of itself: i.e. the count of elements in a list is equal to 0 if an empty list; otherwise it is equal to 1 + the count of the rest of the elements of the list.
The italicized portion of the above definition is where the function call gets made.
private int countRec(ImageNode node) {
if (node == null) {
return 0;
} else {
return 1 + countRec(node);
}
}
A recursive function is useful when it uses the result of the further calls to solve his problem (like an inductive step on mathematics). Your function are not using the return for the countRec() call for anything, and you're still trying to solve the issue without the recursion help. You can solve it by using it, as:
if(node.next != null)
{
node = node.next;
count = countRec()+1;
}
return count;
Of course, since we're telling about getting your code better, you wouldn't even need to use this node var, just doing:
private int countRec() {
if (this.next != null )
return (this.next.countRec())+1;
return 1;
}
Hope that helps.
I will explain the title better for starters. My problem is very similar to the common: find all permutations of an integer array problem.
I am trying to find, given a list of integers and a target number, if it is possible to select any combination of the numbers from the list, so that their sum matches the target.
It must be done using functional programming practices, so that means all loops and mutations are out, clever recursion only. Full disclosure: this is a homework assignment, and the method header is set as is by the professor. This is what I've got:
public static Integer sum(final List<Integer> values) {
if(values.isEmpty() || values == null) {
return 0;
}
else {
return values.get(0) + sum(values.subList(1, values.size()));
}
}
public static boolean groupExists(final List<Integer> numbers, final int target) {
if(numbers == null || numbers.isEmpty()) {
return false;
}
if(numbers.contains(target)) {
return true;
}
if(sum(numbers) == target) {
return true;
}
else {
groupExists(numbers.subList(1, numbers.size()), target);
return false;
}
}
The sum method is tested and working, the groupExists method is the one I'm working on. I think it's pretty close, if given a list[1,2,3,4], it will return true for targets such as 3 and 10, but false for 6, which confuses me because 1,2,3 are right in order and add to 6. Clearly something is missing. Also, The main problem I am looking at is that it is not testing all possible combinations, for example, the first and last numbers are not being added together as a possibility.
UPDATE:
After working for a bit based on Simon's answer, this is what I'm looking at:
public static boolean groupExists(final List<Integer> numbers, final int target) {
if(numbers == null || numbers.isEmpty()) {
return false;
}
if(numbers.isEmpty()) {
return false;
}
if(numbers.contains(target)) {
return true;
}
if(sum(numbers.subList(1, numbers.size())) == (target - numbers.get(0))) {
return true; }
else {
return groupExists(numbers.subList(1, numbers.size()), target);
}
}
For convenience, declare
static Integer head(final List<Integer> is) {
return is == null || is.isEmpty()? null : is.get(0);
}
static List<Integer> tail(final List<Integer> is) {
return is.size() < 2? null : is.subList(1, is.size());
}
Then your function is this:
static boolean groupExists(final List<Integer> is, final int target) {
return target == 0 || target > 0 && head(is) != null &&
(groupExists(tail(is), target) || groupExists(tail(is), target-head(is)));
}
There are no surprises, really, regular checking of base cases plus the final line, where the left and right operands search for a "group" that does or does not, respectively, include the head.
The way I have written it makes it obvious at first sight that these are all pure functions, but, since this is Java and not an FP language, this way of writing it is quite suboptimal. It would be better to cache any function calls that occur more than once into final local vars. That would still be by the book, of course.
Suppose you have n numbers a[0], a[1], ..., a[n-1], and you want to find out if some subset sums to N.
Suppose you have such a subset. Now, either a[0] is included, or it isn't. If it's included, then there must exist a subset of a[1], ..., a[n] which sums to N - a[0]. If it isn't, then there exists a subset of a[1], ..., a[n] which sums to N.
This leads you to a recursive solution.
Checking all combinations is factorial (there's a bit missing on your implementation).
Why not try a different (dynamic) approach: see the Hitchhikers Guide to Programming Contests, page 1 (Subset Sum).
Your main method will be something like:
boolean canSum(numbers, target) {
return computeVector(numbers)[target]
}
computeVector return the vector with all numbers that can be summed with the set of numbers.
The method computeVector is a bit trickier to do recursively, but you can do something like:
boolean[] computeVector(numbers, vector) {
if numbers is empty:
return vector
addNumber(numbers[0], vector)
return computeVector(tail(numbers), vector);
}
addNumber will take vector and 'fill it' with the new 'doable' numbers (see hitchhikers for an explanation). addNumber can also be a bit tricky, and I'll leave it for you. Basically you need to write the following loop in recrusive way:
for(j=M; j>=a[i]; j--)
m[j] |= m[j-a[i]];
The lists of all possible combinations can be reached by asking a very simple decision at each recursion. Does this combination contain the head of my list? Either it does or it doesn't, so there are 2 paths at each stage. If either path leads to a solution then we want to return true.
boolean combination(targetList, sourceList, target)
{
if ( sourceList.isEmpty() ) {
return sum(targetList) == target;
} else {
head = sourceList.pop();
without = combination(targetList, sourceList, target); // without head
targetList.push(head);
with = combination(targetList, sourceList, target); // with head
return with || without;
}
}