I am having problems trying to check if a value is in a linked list or not using recursion. The values in the linked list are between 0 and 5. If the value is in the linked list, the method should return true. However, I am getting wild answers across the board if the value is indeed in the linked list. Some numbers will return false, and some will return true. I am not sure why it is doing this. Thanks!
public boolean contains(int aData)
{
Node currentNode = firstNode;
if(currentNode == null) {
return false;
}
if(currentNode.data == aData) {
return true;
}
else {
return false;
}
}
You're only checking one node (the first node). You're going to be needing something like this:
public boolean contains(int aData, Node node)
{
Node currentNode = node;
// base case; if this node is null, return false
if(currentNode == null) {
return false;
}
// if this node contains the data, return true, otherwise, check next nodes.
if(currentNode.data == aData) {
return true;
} else {
return contains(aData, currentNode.next);
}
}
You can call the above function starting with the head node
contains(5, headNode);
and it will run through your entire list until either a) it finds the data, or b) it has exhausted all options and the data was not found.
As has been mentioned, you are not using recursion and are only checking the first Node. If you want to use recursion, you'll need to call the contains method from within the contains method, which you are not currently doing. Even if you were to simply call it at the end of the method as it stands now, it still wouldn't do anything - think about how you might rewrite it if the method started:
public boolean contains(int aData, Node nodeToCheck)
Recursion has a very well defined form that is used in almost all cases. Essentially the form is:
type method(context) {
if (one of the base cases holds)
return appropriate base value
else
for each possible simpler context
return method(simpler context);
}
This works by progressively breaking the problem down into smaller pieces until the problem is so simple it has an obvious answer (i.e. the base case). The key to using recursion is to ask yourself 'in what situations is the answer obvious?' (i.e. the base cases) and 'when the answer isn't obvious how can I simplify the situation to make it more obvious?'. Don't start coding until you can answer those questions!
In your case you have 2 base cases: you've reached the end of your list or you have found the value. If neither of those cases hold then try again in a simpler context. In your case there's only one simpler context: a shorter list.
Putting all that together you have:
public boolean contains(Node node, int data) {
if (node == null)
return false;
else if (node.value == data)
return true;
else
return contains(node.next, data);
}
Related
I am new to using recursion for my methods. I tend to steer away from them for quite a few reasons. However, for a project, it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph.
Since I am not too well versed in recursion, I don't understand why I am getting the following error.
This method must return a result of type LinkedList.Node
The code I have currently is:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
DFSTime(node.nextNode);
}
}
It is unfinished code since I still need to implement some logic, however, I don't understand how to eliminate the error. Is there something very basic that I am missing?
The reason of the compilation error is pretty trivial. The compiler clearly tells that didn't provide the result to return for all possible cases.
The more important is that your current approach is not correct.
it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph
There are crucial things to consider:
Field nextNode is very suspicious. If each Node holds a reference pointing to a single node only, in fact the data structure you've created by definition isn't a Graph, but a Singly linked list. And doesn't make sense to implement DFS for a list. Every node should point to a collection of nodes, no to a single node.
You have to distinguish somehow between unvisited nodes and nodes that are already visited. Or else you might and up with infinite recursion. For that, you can define a boolean field isVisited inside the Node, or place every visited node into a HashSet.
Since you've chosen to create a recursive implementation of DFS, you don't need to create a stack. It's required only for iterative implementation.
Don't overuse global variables. I guess you might want to be able to check whether it is possible to reach different airports of destination without reinstantiating the graph.
Use getters and setters instead of accessing fields directly. It's a preferred practice in Java.
Your method might look like this (it's not necessary that element should be of type String it's just an illustration of the overall idea):
public Node DFSTime(Node node, String destinationAirport){
if(node == null || node.isVisited()) {
return null;
}
if (node.getElement().equals(destinationAirport)) {
System.out.println("The destination airport was found");
return node;
}
node.setVisited(true);
for (Node neighbour: node.getNeighbours()) {
Node result = DFSTime(neighbour, destinationAirport);
if (result != null) return result;
}
return null;
}
And the node might look like this:
public class Node {
private String element;
private List<Node> neighbours;
private boolean isVisited;
public Node(String element, List<Node> neighbours) {
this.element = element;
this.neighbours = neighbours;
}
public void setVisited(boolean visited) {
isVisited = visited;
}
public boolean isVisited() {
return isVisited;
}
public void addNeighbours(Node neighbour) {
neighbours.add(neighbour);
}
public String getElement() {
return element;
}
public List<Node> getNeighbours() {
return neighbours;
}
}
You should have a default return statement at the end of the function after the closing of the else.
In methods conditional blocks (if-else), you need to make sure you are returning appropriate Type from all conditional statements, so that there is no compile-time error. In your case, else block is recursively calling DFSTime(..) without returning anything.
You might want to return reference which gets called via recursive call, something like below:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
Node node = DFSTime(node.nextNode);
return node;
}
}
I implemented the Set ADT using the standard approach with nodes (TreeNodes) using a binary search tree.
I have the task of implementing it using the same old nodes except that they have an additional boolean field "active", which can "switch on" (setActive(true)) or "switch off" (setActive(false)) the nodes when removing. This keeps removed nodes there, but they are ignored when we implement toString(), which returns the items in the set.
I was able to implement all the methods of the Set ADT apart from removeAny() (that removes anything from the set, essentially "switches it off"). The problem is that I have to find any node that is "switched on". For this, I have to go through each node and check if one is active. I tried to write the code using recursive calls, but got confused about what to return. Here is my attempt (in Java):
public T removeAny() throws Exception {
if (size == 0) {
throw new Exception ("You cannot remove anything since the set is empty!");
}
return removeAnyHelper (root);
}
public T removeAnyHelper (OnOffTreeNode <T> node) {
if (node == null) {
return root.getValue();
}
if (node.getActive() == true) {
size--;
node.setActive(false);
return node.getValue();
}
removeAnyHelper (node.getLeft());
return removeAnyHelper (node.getRight());
}
How can I fix this method? What should I return?
I tried some if-statements to return both removeAnyHelper (node.getLeft()) and removeAnyHelper (node.getRight()), but this didn't work.
If the node is null, you presumably need to return null (since nothing was removed).
If the recursive call on the left child doesn't return null, it means we removed a node and we need to return it. Otherwise we need to return the result of the call on the right child.
Turning that into code:
public T removeAnyHelper (OnOffTreeNode <T> node) {
if (node == null) {
return null;
}
if (node.getActive()) { // == true is unnecessary
size--;
node.setActive(false);
return node.getValue();
}
T removedNode = removeAnyHelper (node.getLeft());
if (removedNode != null)
return removedNode;
else
return removeAnyHelper (node.getRight());
}
Although I wouldn't really recommend using active/inactive flags for nodes in a BST - deleting a node isn't particularly hard to implement and avoids the problem of having a large number of inactive nodes.
More generally speaking, there are also self-balancing BST's, which avoid reduced efficiency due to unbalanced trees.
Well I don't think removeAny is a proper method for a Set, but anyway.
You can (and probably should) removeAny by removing the first leaf:
private T removeAnyHelper(OnOffTreeNode <T> node) {
if (!present(node.getLeft() && !present(node.getRight())) {
// no children -> this is a leaf, return
node.setActive(false);
return node.getValue();
}
// return left first, or right if left not present
if (present(getLeft())) {
return removeAnyHelper(getLeft());
}
return removeAnyHelper(getRight());
}
private boolean present(OnOffTreeNode<T> node) {
return node != null || node.isActive();
}
Note that you also have a mistake in your base removeAny method because it doesn't check for root's active state:
public T removeAny() throws NoSuchElementException {
if (size == 0 || !root.isActive()) {
throw new NoSuchElementException ("cant remove");
}
return removeAnyHelper(root);
}
class Link{
private int value;
private Link next;
}
I am asked to write a recursive method to delete last occurrence of a certain value, say 4.
before 2->3->4->5->4->2
after 2->3->4->5->2
The last occurrence only. I know how to delete all occurrence but I can't tell if its the last occurrence. No helper method is allowed.
The one to delete all occurrence
public Link deleteAll(){
if (next == null){
return value==4? null:this;
}else{
if (value == 4){
return next.deleteAll();
}
next = next.deleteAll();
return this;
}
}
You can declare a pointer to the last occurred node and delete that node when reached the last element in list. Following steps explains that -
Declare two pointers one is next as in your above code another can be temp.
Iterate through list using next like you doing in deleteAll method above.
If you find the node you looking for assign that node to temp.In your case 4.
When next is null you reached the end of list now delete, whatever node is in temp delete that node. If temp is still null than no node found in given key.
EDIT:
Possible pseudo Code in case of recursion:
public void deleteLast(Node node,Node temp,Node prev, int data)
{
if(node==null)
{
if(temp!=null && temp.next.next!=null){
temp.next = temp.next.next;}
if(temp.next.next==null)
temp.next = null;
return;
}
if(node.data==data)
{
temp = prev;
}
prev = node;
deleteLast(node.next, temp, prev, int data);
}
Above code should be able to solve your problem. I made some edit in my approach which should be obvious from the code but let me describe it below
I added a prev pointer. Because if we want to delete a particular node we need to assign its next to prev node's next.So, we need the prev node not the node that we want to delete.
I think this change will follow in iterative approach too.
Not really answering your exact question, but as an alternative option, you might consider the following.
Write a recursive method to delete the first occurrence of a specified value, something like this:
public Link deleteFirst(int target) {
if (value == target) {
return next;
}
next = (next == null) ? null : next.deleteFirst(target);
return this;
}
Then you could write a reverse() method as either an iterative or recursive method as you see fit. I haven't included this, but googling should show some useful ideas.
Finally the method to remove the last occurrence of a value from the linked list could then be written like this:
public Link deleteLast(int target) {
return reverse().deleteFirst(target).reverse();
}
Note that as long as your reverse() method is linear complexity, this operation will be linear complexity as well, although constants will be higher than necessary.
The trick is to do the work on the way back -- there is no need for additional parameters, helpers or assumptions at all:
Link deleteLast(int target) {
if (next == null) {
return null;
}
Link deleted = next.deleteLast(target);
if (deleted == null) {
return value == target ? this : null;
}
if (deleted == next) {
next = deleted.next;
}
return deleted;
}
Here is the code for the implementation of the Binary Search Tree:
public class BST<T extends Comparable<T>> {
BSTNode<T> root;
public T search(T target)
{
//loop to go through nodes and determine which routes to make
BSTNode<T> tmp = root;
while(tmp != null)
{
//c can have 3 values
//0 = target found
//(negative) = go left, target is smaller
//(positive) = go left, target is greater than current position
int c = target.compareTo(tmp.data);
if(c==0)
{
return tmp.data;
}
else if(c<0)
{
tmp = tmp.left;
}
else
{
tmp = tmp.right;
}
}
return null;
}
/*
* Need a helper method
*/
public T recSearch(T target)
{
return recSearch(target, root);
}
//helper method for recSearch()
private T recSearch(T target, BSTNode<T> root)
{
//Base case
if(root == null)
return null;
int c = target.compareTo(root.data);
if(c == 0)
return root.data;
else if(c<0)
return recSearch(target, root.left);
else
return recSearch(target, root.right);
}
Why do I need the recursive helper method? Why can't I I just use "this.root" to carry out the recursive process that is taking place? Furthermore, if screwing up the root property of the object this method is being called on is a problem, then how is does the helper method prevent this from happening? Does it just create a pointer that is separate from the this.root property, and therefore won't mess up the root property of the object that the method is being called on?
Sorry if the question doesn't seem straight forward, but if anyone can enlighten me on what's exactly going on behind the scenes I would really appreciate it.
The method needs a starting point. It needs to have a non changing Target node and it needs to compare it with some other node to see if they are a match lets call this node current instead of root since it is the current Node the recursive method is evaluating. There really isn't a concise way of doing this when using a recursive method other than using a helper function and passing in both variables (this is the case for many recursive methods). As you said stated if you updated root you would completely alter your tree when going left or right which you wouldn't want to do. The helper function is used because it gives your recursive method a starting point. And it also keeps track of the current node you are working on as you said the method points to the Node object being evaluated but doesn't make any changes. When going left or right it doesn't modify anything it just passes in a reference to the left or right node and continues to do this until the target is found or the base case is hit.
I tried to convert a List from 3{1{,2{,}},5{4{,},6{,}}}
to a Binary Tree like this
3
1 5
2 4 6
I thought it would be easier to use recursion but I get stuck.
public void ListToTree (ArrayList al) {
Iterator it = al.iterator();
// n is the Tree's root
BSTnode n = new BSTnode(it.next());
recurse(al,it,n);
}
void recurse (ArrayList al, Iterator it, BSTnode n) {
if(!it.hasNext()) return;
Object element = it.next();
if(element=="{"){
recurse(al,it,n.left());
return;
} else if (element==",") {
recurse(al,it,n.right());
return;
} else if (element =="}") {
}
}
I don't know how to proceed and was wondering if it's the right track. Please give me some hints how to solve it. Moreover, I realize I often get stuck on recursive questions. Is it because I always want to break it down? Should I just think top-down and double-check if it's correct? Thanks in advance !
Firstly: are you bound to that terrible list representation? You can easily build a BST based on the BST rules with this code:
void insert(Node n, int value) {
if(n == null) {
n = new Node(value);
} else if(value < n.value) {
if(n.left == null) {
n.left = new Node(value);
return;
}
insert(n.left, value);
} else if(value > n.value) {
if(n.right == null) {
n.right = new Node(value);
return;
}
insert(n.right, value);
}
}
You really don't have to pass the iterator. Just use the values from the list. Also it is usually unadvised to use implementation types in method signatures. (i.e. ArrayList -> List).
Another big mistake here is that you don't use == for value comparison, that is for reference comparison. Use equals instead, but you should downcast the Object after an instanceof test e.g.:
if( element instanceof String) {
String seperator = (String)element;
if("{".equals(separator))
//do sth...
Btw the thing you are missing from the code is the actual insertion and the backwards navigation.
After you found the right subtree by navigating with the {-s and ,-s, check whether the element is an Integer then set it as a value for the current node. Backwards navigation should be in the } branch by either returning one level from the recusion and some tricks or calling the method on the parent of the actual node.
But I don't suggest you to follow this direction, it is much easier to just use the values from the list and the simple insertion method.