Given a string to search for, I want to write a recursive function that takes in only one parameter (The string to search for). The function will search for the value recursively and if it is found then it will remove the item and return it. If it is not found then, the function will reach the end of the list and return null. What I have so far I think is the right idea except it is not functioning properly:
Main Test Class
public static void main(String[] args) {
RecLinkedList list = new RecLinkedList();
list.add("A");
list.add("B");
list.add("D");
list.add("C", 2);
list.add("E", 4);
list.add("G", 6); //this should be invalid
System.out.println( list );
System.out.println( list.remove( 1 ).getValue() );
System.out.println( list.remove("D").getValue() );
System.out.println( list.remove("G").getValue() );
System.out.println( list.size() );
System.out.println( list );
}
Linked List Class (Showing only what I need help on)
public class RecLinkedList {
private Node first;
private int size = 0;
public RecLinkedList(){
first = null;
}
public boolean isEmpty() {
return first == null;
}
public Node remove( String s ){
return remove( s, 0, first );
}
private Node remove( String s, int count, Node list ){
if( list == null ){
return null;
}else if( s.equals(s) ){
first = list.getNext();
return list;
}else if( s.equals(count+1) ){
Node n = list.getNext();
if( list.getNext() != null ){
list.setNext( list.getNext().getNext() );
}
return n;
}else{
return remove( s, count+1, list.getNext() );
}
}
So far, I am able to remove the item but as of now the item "A" is getting removed when it should not be. The final list should be A,C,E. (G should return and print null because it does not exist). I think I am close, but off by something minor, but I can not seem to figure it out.
There are several errors in your code (see comments below) :
private Node remove( String s, int count, Node list ){
if( list == null ){
return null;
}else if( s.equals(s) ){ // comparing s to itself means you always remove
// the first element from the list (since this
// condition is always true)
first = list.getNext();
return list;
}else if( s.equals(count+1) ){ // comparing the String s to an int - makes
// no sense, will never be true
Node n = list.getNext();
if( list.getNext() != null ){
list.setNext( list.getNext().getNext() );
}
return n;
}else{
return remove( s, count+1, list.getNext() );
}
}
It seems to me like there is some ambiguity in your question. I understand that your method should search for an element, remove it if present, and return the same object. If the element is not present, the method should return null. That seems pretty straight-forward since most of your utility methods are already implemented in LinkedList. I thus recommend to extend that class:
public class RecLinkedList<E>
extends LinkedList<E>
{
public E removeAndReturn(E element)
{
E result;
if (this.contains(element)) {
remove(element);
result = element;
}
else {
result = null;
}
return result;
}
}
I don't see why you would want to implement this recursively.
This could clearly be written more concisely, but the explicit if-else should make it clearer.
EDIT: The more concise and probably better implementation would be:
public E removeAndReturn(E element)
{
return remove(element) ? element : null;
}
Related
I don't have much on this... my assignment is to create a recursion method that will output the highest value in an ArrayList of integers.
public static int maxValue(ArrayList<Integer> a)
{
if (a.isEmpty()) throw new NoSuchElementException ("Can't compute max of empty list.");
if(a.size()==1){return a.get(0);}
else {
//not sure what to add here for the recursion
}
}
A way to do this is actually compare the first two values and remove the smallest one ( or one of them if equal) and set a base case of list size 1 like this:
public static int maxValue(ArrayList<Integer> a)
{
if (a.isEmpty()) return -1;
if (a.size() == 1) return a.get(0);
if (a.get(0) <= a.get(1))
{
a.remove(0);
} else
{
a.remove(1);
}
return maxValue(a);
}
Try this:
import java.util.List;
import static java.util.Math.*;
import java.util.NoSuchElementException;
import static java.util.Objects.*;
public static int maxValue( List<Integer> list )
{
if( isNull( list ) ) throw new IllegalArgumentException( "list is null." );
if( list.isEmpty() ) throw new NoSuchElementException( "Can't compute max of empty list." );
var size = list.size();
var head = list.get( 0 );
var retValue = size == 1 ? head : max( head, maxValue( list.sublist( 1, size ) );
return retValue;
}
List.subList() does not return a copy of the (sub)list, but a new view on the underlying list.
If the requirements permit, you could add a second parameter n, and pass the size of ArrayList.
...
System.out.println(maxValue(arrlst, arrlst.size()));
...
public static int maxValue(ArrayList<Integer> a, int n) {
if (n == 1)
return a.get(0);
return Math.max(a.get(n - 1), maxValue(a, n - 1));
}
I have two queue lists and I want to check if q2 is reverse for q1.
This is my code.
public static boolean reverse ( LinkedQueue q1, LinkedQueue q2 ) {
for ( int i = 0; i < q1.length() ; i ++)
if ( q1.serve () == q2.gettail().getdata() ) {
q1.enqueue(q1.serve ());
return true ;
} else {
return false;
}
return false;
}
I just check if the head of q1 equal the tail of q2 but my problem is I want to check for all elements that they are equal and I don't know how.
The way one normally approaches it is to return true in the end. Iterate through and only return false if i+n i+length-n.
Assuming everything else is working it will be like this.
public static boolean reverse ( LinkedQueue q1, LinkedQueue q2 ) {
for ( int i = 0; i < q1.length() ; i ++) {
if ( q1.serve () == q2.gettail().getdata() ) {
q1.enqueue(q1.serve ());
} else {
return false;
}
}
return true;
}
Note: You also missed curly brackets around your for.
My code undos the added elements one by one starting with the latest add. It does everything correctly unless there is only one node left in a list and my code does not undo/remove it from the list. For example:
[A, B, C, D, E] //call undo()
[A, B, C, D] //call undo()
[A, B, C] //call undo()
[A, B] //call undo()
[A] //call undo() and it throws Exception here <------------------
Exception in thread "main" java.lang.NullPointerException
If I undo [A] it should return empty list [].
NOTE: I HAVE TO USE A DUMMY NODE called beginMarker and endMarker which have a value of null, so the last element looks like this:
beginMarker <-> "A" <-> endMarker
For the last element, the code checks if the size equals to 1 and it's true and proceeds further but does not empty out the list. Any help would be appreciated!
public void add(x){
.........
undoStack.push(newNode);
}
public void undo(){
if(undoStack.isEmpty()){
throw new RuntimeException("Undo history is empty");
}
else{
Node<T> object = undoStack.topAndPop();
redoStack.push(object);
if(this.size() == 1){
beginMarker = object.next;
beginMarker.next = null;
//beginMarker.next = null;
}
if(object.prev == beginMarker){
beginMarker.next = object.next.prev;
object.next.prev = beginMarker;
}
else if(object.next == null){
object.prev.next = null;
}
else{
object.next.prev = object.prev;
object.prev.next = object.next;
}
theSize--;
modCount--;
countUndone++;
}
Class SimpleStack
public class SimpleStack<AnyType>{
// Tracks the top node of stack.
private Node<AnyType> topOfStack;
// Construct the stack.
public SimpleStack( ) {
topOfStack = null;
}
// Test if the stack is logically empty.
// #return true if empty, false otherwise.
public boolean isEmpty( ) {
return topOfStack == null;
}
// Make the stack logically empty.
public void clear( ) {
topOfStack = null;
}
// Insert a new item into the stack.
// #param x the item to insert.
public void push( AnyType x ) {
topOfStack = new Node<AnyType>( x, topOfStack );
}
// Remove the most recently inserted item from the stack.
// #throws UnderflowException if the stack is empty.
public void pop( ) {
if( isEmpty( ) )
throw new RuntimeException( "SimpleStack pop" );
topOfStack = topOfStack.next;
}
// Get the most recently inserted item in the stack.
// Does not alter the stack.
// #return the most recently inserted item in the stack.
// #throws UnderflowException if the stack is empty.
public AnyType getTop( ) {
if( isEmpty( ) )
throw new RuntimeException( "SimpleStack empty in getTop" );
return topOfStack.data;
}
// Return and remove the most recently inserted item
// from the stack.
// #return the most recently inserted item in the stack.
// #throws UnderflowException if the stack is empty.
public AnyType topAndPop( ) {
if( isEmpty( ) )
throw new RuntimeException( "SimpleStack empty in topAndPop" );
AnyType topItem = topOfStack.data;
topOfStack = topOfStack.next;
return topItem;
}
// A singly linked Node which contains data and a link to another
public class Node<T>{
public T data;
public Node<T> next;
public Node(T d, Node<T> n ){
this.data = d;
this.next = n;
}
}
}
I would not be surprised the NPE occurs here :
if(object.prev == beginMarker){
beginMarker.next = object.next.prev;
// ^^^^
// is it here ? object.next is null in your case
object.next.prev = beginMarker;
}
It should fix it to simply write
if(object.prev == beginMarker && object.next != null) {
beginMarker.next = object.next.prev;
object.next.prev = beginMarker;
}
However, you don't really have to particularize the case size() == 1. A simpler implementation would be (assuming you add a pointer to the end of the list) :
public void undo() {
if (undoStack.isEmpty()) {
throw new NoSuchElementException("Undo history is empty");
} else {
Node<T> object = undoStack.topAndPop();
redoStack.push(object);
object.prev.next = object.next;
object.next.prev = object.prev;
theSize--;
modCount--;
countUndone++;
}
}
This should work since using an endMarker will prevent you from having any null node in the list.
I have written a recursive program for checking whether a binary tree is a BST.
I have written a base case which is returning true or false, but I have got confused in recursive case.
This program makes the recursive call but it is not working though I feel its fine.
public class BinaryBSTChecker {
public static boolean isBinaryBST(Node node) {
if ( node != null) {
Node leftNode = node.getLeftNode();
Node rightNode = node.getRightNode();
int value = node.getValue();
isBinaryBST(leftNode) ;
isBinaryBST(rightNode) ;
boolean leftIsOk = isLeftOK(leftNode , value);
boolean rightIsOk = isRightOK(rightNode, value);
return (leftIsOk && rightIsOk);
}
return false;
}
private static boolean isLeftOK(Node leftNode, int value) {
boolean leftOK = false;
if (leftNode != null) {
if (leftNode.getValue() < value) {
leftOK = true;
}
} else {
leftOK = true;
}
return leftOK;
}
private static boolean isRightOK(Node rightNode, int value) {
boolean rightOK = false;
if (rightNode != null ) {
if (rightNode.getValue() > value) {
rightOK = true;
}
} else {
rightOK = true;
}
return rightOK;
}
}
Client code:
public class TestingClient {
public static void main (String[] args) {
Node node = getBSTTree() ;
System.out.println("------Is Binary BST ?------>"
+ BinaryBSTChecker.isBinaryBST(node));
}
public static Node getBSTTree() {
Node node = new Node(9);
Node leftNode = new Node(7);
Node rightNode = new Node(11);
Node leftNode2 = new Node(67);
Node rightNode2 = new Node(8);
Node leftNode3 = new Node(10);
Node rightNode3 = new Node(12);
node.setLeftNode(leftNode);
node.setRightNode(rightNode);
leftNode.setLeftNode(leftNode2);
leftNode.setRightNode(rightNode2);
rightNode.setLeftNode(leftNode3);
rightNode.setRightNode(rightNode3);
return node;
}
}
The above tree isn't a BST as 67 > 7.
So this should return false, but I am getting true for this case, and in fact for all cases.
why are you returning false at end of public static boolean isBinaryBST(Node node) ?
Return true there and should be ok.
edit:
obviously it was a mistake but i did not take a good look at code.
One more thing here.
There is only isLeftOK and isRightOk called, but also on left & right nodes but there are also calls
isBinaryBST(leftNode) ;
isBinaryBST(rightNode);
It seems that results of those are ignored and this is an issue.
return should be sth like:
return (leftIsOk && rightIsOk && isBinaryBST(leftNode) && isBinaryBST(rightNode));
You're ignoring the return value of isBinaryBST in the recursive calls, so the function just returns whether the root's children is correct.
But the way you tried to solve the problem fundamentally won't work.
Take this tree:
5
/
3
\
7
It's not a valid BST, as 7 > 5.
There's no way you can check for this by only looking at the direct children.
The recommended approach would be passing in a min and max to your function, i.e. the signature would be:
boolean isBinaryBST(Node node, int min, int max)
And simply checking whether the current node's value is between the two (or the node is null) (no need for helper functions), and making the appropriate recursive calls to the children (and remember to check their return values!). The general idea would be: (pseudo-code)
return (current node is between min and max)
&& (left subtree is okay, i.e. recursive call with left child)
&& (right subtree is okay, i.e. recursive call with right child)
I'll leave the exact details to you to work out.
In the above example, when we get to 7, min = 3 and max = 5, so we see that 7 > max, and return false.
Add null checks or it will go in infinite loop
if(leftNode != null)
isBinaryBST(leftNode) ;
if(rightNode != null)
isBinaryBST(rightNode) ;
boolean leftIsOk = true;
boolean rightIsOk = true;
if(leftNode != null)
leftIsOk = isLeftOK(leftNode , value); ;
if(rightNode != null)
rightIsOk = isRightOK(rightNode, value);
return (leftIsOk && rightIsOk);
what does this error mean? and how do i solve it?
foreach not applicable to expression type.
im am trying to write a method find(). that find a string in a linkedlist
public class Stack<Item>
{
private Node first;
private class Node
{
Item item;
Node next;
}
public boolean isEmpty()
{
return ( first == null );
}
public void push( Item item )
{
Node oldfirst = first;
first = new Node();
first.item = item;
first.next = oldfirst;
}
public Item pop()
{
Item item = first.item;
first = first.next;
return item;
}
}
public find
{
public static void main( String[] args )
{
Stack<String> s = new Stack<String>();
String key = "be";
while( !StdIn.isEmpty() )
{
String item = StdIn.readString();
if( !item.equals("-") )
s.push( item );
else
StdOut.print( s.pop() + " " );
}
s.find1( s, key );
}
public boolean find1( Stack<String> s, String key )
{
for( String item : s )
{
if( item.equals( key ) )
return true;
}
return false;
}
}
this is all my code
Are you using an iterator instead of an array?
http://blogs.oracle.com/CoreJavaTechTips/entry/using_enhanced_for_loops_with
You cannot just pass an Iterator into the enhanced for-loop. The 2nd line of the following will generate a compilation error:
Iterator<Penguin> it = colony.getPenguins();
for (Penguin p : it) {
The error:
BadColony.java:36: foreach not applicable to expression type
for (Penguin p : it) {
I just saw that you have your own Stack class. You do realize that there is one already in the SDK, right? http://download.oracle.com/javase/6/docs/api/java/util/Stack.html
You need to implement Iterable interface in order to use this form of the for loop: http://download.oracle.com/javase/6/docs/api/java/lang/Iterable.html
Make sure your for-construct looks like this
LinkedList<String> stringList = new LinkedList<String>();
//populate stringList
for(String item : stringList)
{
// do something with item
}
Without code this is just a grasp at straws.
If you're trying to write your own list-find method, it would be like this
<E> boolean contains(E e, List<E> list) {
for(E v : list) if(v.equals(e)) return true;
return false;
}