I need help with my homework
My question is: How to complete the method findMaxItem below to return a pointer to the largest element of the linked list given by the parameter ptr, or return null if the list is empty. The solution must be a recursive one.
This my my answer but is not correct:
public static Node findMaxItem (Node ptr) {
if (ptr == null) {
return null;
} else {
if (ptr.next.data > ptr.data) {
Node n = ptr.next;
if (ptr.next.data >= n.data) {
n = ptr.next;
//ptr = n.next;
findMaxItem(n);
} else {
ptr = ptr.next;
findMaxItem(ptr);
}
ptr = n.next;
findMaxItem(ptr);
ptr = n;
}
// ptr = ptr.next;
// findMaxItem(ptr);
}
return ptr;
}
Thanks for help everyone :)
You've at least got the first part right: if the list is empty, return null. This is the base case of the recursion.
if (ptr == null) return null;
You're meant to use recursion for the rest of the cases. But how?
If the list is not empty, you can divide it into two parts: the first item, and the rest of the list. Would it help you "find the max item" in the rest of the list?
Node restOfTheList = ptr.next;
Node maxOfRestOfTheList = findMax(restOfTheList);
Now you have the first item, referenced by ptr, and the item with the greatest value in the rest of the list. If you compare the data in those, you can figure out which has the greatest value. And which ever it is, that is the node with the largest item. Does that make sense?
if data of "ptr" is greater than data of "maxOfRestOfTheList": return ptr
else: return maxOfRestOfTheList;
You'll also have to deal with the case where there is only one item in the list. In that situtation restOfTheList is empty.
One possible solution is to create a method that receive the array with the values -1 and the last value. Then check if the next last element is greater that the one you have or not, if it is, the new value is the current maximum remove it and call the same method by using the new array (with the removed value) and the current maximum.
The base case will be when there is only one element in the array, take or compare it with the last maximum value you passed to the recuerdo be función and return the greater value of these two. This last will be the maximum in a recursive way.
I have no possibility to write the code right now but in meta-code it should be something like this
private int finalMax
public void maxRecursive(arrayList<int>List, Int tempMax){
//Base case
Int newTempMax = tempMax
If (tempMax >list.get(list.size-1)){
newTempMax=list.get(list.size()-1)
}
If (list.size()>1){
List.remove(list.size()-1)
maxRecursive(list, newTemMax)
}else{
finalMax=newTempMax
}
}
As I said this is nothing more than pseudo-code that looks adapted to java, I cannot son anything better right now but AI think that you can get the Idea from here.
Best!
Related
Alright, so cut a long story short, what I'm trying to do here is remove all instances of value e from a doubly linked list. As far as I know, my logic is at least mostly right, but for some off reason it isn't actually removing any of the nodes in my test cases.
public boolean removeAll(int e) {
DIntNode dummy = head,next = null;
if (head == null)
return false;
while (dummy != null) {
if (dummy.getData() == e) {
next = dummy.getNext();
dummy.getNext().setPrev(null);
dummy = next;
return true;
}
else
dummy = dummy.getNext();
}
return false;
}
This is what I currently have for my code of the metho. My logic here was to use a dummy DIntNode that starts at the head and a "next" node to help me shrink the list, so to speak. In other words, if the list was something like "1<-> 1 <-> 2 <-> 3", the function would change it to "2<->3", in theory. The reason this is a boolean function is because I'm required to return true if the given value is removed form the list.
Is there just another step in the logic that I'm missing, or is the methodology itself just unreliable? I'm very unsure at this point, so any and all help would be greatly appreciated.
You set
dummy.getNext().setPrev(null);
But previous node also have reference to next node you try to remove. You should set this reference to next active value.
That because when you want to get all linked list previous value still know about node you remove, because of next node reference
You can try with the following code:
if (dummy.getData() == e) {
DIntNode temp = dummy.getPrevious();
temp.next = dummy.getNext();
temp = dummy.getNext();
temp.previous = dummy.getPrevious();
return true;
}
This used the previous reference. So the previous node will now have reference to the next node of your dummy node (node to be deleted). And similarly, the next node of dummy node will have reference of previous node of your dummy node. So, the dummy node will loose its connection/link from its doubly link list and that's what we want!
Please try.
Two issues with the code:
When relinking a doubly linked list, where removing B from A - B - C, you need to set the next node for A to be C as well as the previous node for C to be A. With trying to keep you method names:
A.setNext(current.getNext());
C.setNext(current.getPrev());
With your code, if you find an occurrence, you return, which means that no other instances will be removed since you jump out of that method. You will probably need a new boolean removed variable, that is set to false, return true changed to removed = true and return false changed to return removed.
The method exits after the first encounter of 'e'.
If you want to remove all instances of 'e', then you should have something like this:
boolean listChanged = false;
while (dummy != null) {
if (dummy.getData() == e) {
// update list
...
listChanged = true;
}
...
}
return listChanged;
Also, you should not write your code like this:
dummy.getNext().setPrev(...); // throws NPE if next is null
Beginner here using Java (first year student), and am unable to get the below function to work. The goal is to use recursion and a helper function to compute the size of a singly linked list. When running the code against test lists, it keeps returning List changed to [].
I'm struggling in general with Java, so any help is appreciated. Thank you
public class MyLinked {
static class Node {
public Node(double item, Node next) {
this.item = item;
this.next = next;
}
public double item;
public Node next;
}
int N;
Node first;
public int sizeForward() {
return sizeForwardHelper(first);
}
public int sizeForwardHelper(Node n) {
Node current = first;
if (current == null) {
return 0;
} else {
first = first.next;
return sizeForward() + 1;
}
}
I believe I have the first portion set up to return 0 if there are no elements in the List. I believe it's the second part that isn't setting up correctly?
Thanks
Because it’s important for your learning to not spoonfeed you, I’ll describe an approach rather than provide code.
Use this fact:
The length of the list from any given node to the end is 1 plus the length measured from the next node (if there is one).
Usually (as would work here), recursive functions take this form:
If the terminating condition is true, return some value
Otherwise, return some value plus the recursively calculated value
When writing a recursive function, first decide on the terminating condition. In this case, n == null is the obvious choice, and you’d return 0, because you’ve run off the end of the list and the length of nothing (ie no node) is nothing. This also handles the empty list (when first is null) without any special code.
Otherwise, return 1 (the length of one node) plus the length of next.
Put that all together and you’ll have your answer.
——
Hint: The body of the recursive helper method can be coded using one short line if you use a ternary expression.
Instead of calling your wrapper function call your helper function recursively. Try the following:
public int sizeForward () {
return sizeForwardHelper (first);
}
public int sizeForwardHelper(Node n) {
if (n == null) // base case
return 0;
return sizeForwardHelper(n.next) + 1; // count this node + rest of list
}
Your method that computes the size of the list actually modifies the list in the process (with first = first.next; you set the first element to the next, and since there is a recursion, the first element always end up being null which is equivalent to an empty list with your design). Your method will work once, but your list will be empty afterwards.
To illustrate this, I added a print next to the instruction first = first.next; and wrote the following main:
public static void main(String[] args) {
Node n2 = new Node(2d, null);
Node n1 = new Node(1d, n2);
Node n = new Node(0, n1);
MyLinked l = new MyLinked(n);
System.out.println("The first element is: "+l.first.item);
System.out.println("The size is: "+l.sizeForward());
System.out.println("The first element is: "+l.first);
}
It yields:
The first element is: 0.0
first is set to 1.0
first is set to 2.0
first is set to null
The size is: 3
The first element is: null
Clearly, you should not modify the list while computing its size. The helper method should return 0 if the node is null (empty list), and 1 plus the size of the rest of the list otherwise. Here is the code.
public int sizeForwardHelper(Node n) {
if (n == null)
return 0;
else
return sizeForwardHelper(n.next) +1;
}
The goal of the arg free method sizeForward() is just to call the helper. The helper should not use it though.
Looking for help again as my professor seems to do an awful job of explaining things (assumes that we know way too much about java programming, when in fact, it's the first java class most of us are taking).
Not looking for someone to write the code for me, but rather someone who can let me know if I'm on the right track and guide me in the right direction. I really want to learn this stuff, not be spoon-fed it, but the professor is making it very hard to do so, so I turn here for help.
The question is to take a LinkedList and create a function to delete the k-th element in that list. I have figured out how to remove the first item if k == 0, but I'm getting lost on how to access the proper element for the "k" within my loop. Here's what I have so far:
public class MyLinked {
static class Node {
public Node(double item, Node next) {
this.item = item;
this.next = next;
}
public double item;
public Node next;
}
int N;
Node first;
// delete the kth element (where k is between 0 and N-1 inclusive)
public void delete(int k) {
if (k < 0 || k >= N) throw new IllegalArgumentException();
{
if (k == 0) {
remove(first.item);
} else if (k > 0) {
kElem = LinkedList.get();
remove(kElem);
}
}
}
}
I'm trying to assign a variable to the .get function but I am definitely wrong there, but not quite sure how to go about this. I know I need to get the value of the k-th element and delete it, however.
I'm also aware that after this, I need to adjust the pointers within the LinkedList to fill the gap where the element I deleted would have been.
Thank you.
Your Link List looks like this:
On this image prev is the object in front of the object you want to delete. Cur is the object you want to delete.
You loop until the next-pointer targets the object you want to delete. After that you set the next pointer of prev to the the object, which follows cur (cur is the object you want to delete).
In pseudo-code it would look like this:
prev = head;
while(prev.next != cur) {
prev = prev.next
}
After this step the prev is on the correct position.
You can see, that this algorithm works with every case except removing the head. You can make a check if you are removing the head and use a different algorithm or you use a dummy-node. Use the dummy-node as head and a dummy-node as tail (here not displayed, but used in double-linked-lists). This dummy-nodes are called sentinels. You won't ever remove this sentinel but your algorithm works without the additional-check because you will remove elements > 0.
Sources:
https://www.cs.cmu.edu/~adamchik/15-121/lectures/Linked%20Lists/linked%20lists.html
In the comments I saw a discussion about clean-code. If you are learning clean-code you will see, that a lot of algorithms are easier to understand, if the variables express their purpose. For example N should be size. But in a different context it could be an upper-limit-of-elements for a cache. There is a good book on this topic: Clean Architecture: A Craftsman's Guide to Software Structure and Design (Robert C. Martin Series)
What do you think is easier to read:
int[][] a = new int[100][200];
for(int i = 0; i < a.length) {
for(int j = 0; j < a[i].length) {
a[i][j] = i*j;
}
}
or this:
int[][] productOfRowColumns = new int[100][200];
for(int row = 0; i < productOfRowColumns.length) {
for(int column = 0; j < productOfRowColumns[row].length) {
productOfRowColumns[row][column] = row*column;
}
}
First go to the k-1 element. Set element.next=element.next.next. Thats how you skip the element, which should be deleted.
Exception: When k=0 (the head element), just set head=head.next.
Optionally you can set next = null for the deleted element (when you went for k-1 elements, deleted=element.next before setting element.next=element.next.next. then say deleted.next=null to clear its next-pointer.
There is also a second common way where you go to the kth element, but you always save the previous (k-1) element in a variable. Performance wise it is worse, because you update 2 variables in each step. It could be more intuitive. Check that video: https://www.youtube.com/watch?v=2RwWsHePdr8 (I hope yt-links are allowed on SO)
By the way, your
static class Node {
public Node(double item, Node next) {
this.item = item;
this.next = next;
}
public double item;
public Node next;
}
int N;
Node first;
is your implementation of the list. LinkedList is the implementation provided by java. https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html. You can not mix them.
Hints:
Don't forget to decrease the size of the list (N--;)
You can "go" to the n-th element with "Node current=head; for(int i = 0; i < n; i++) current=current.next;"
What I mean with "head" is your "first". It is the first element of the list.
The "get" method does not do what you want. You will need to write the code to iterate to position k-1 and switch the pointer, as you said:-
eg. list 1->2->3->4, k=2
iterate using next pointer upto 2, switch the next pointer to point to 4. You don't need to do anything else(remove etc)
I'm having a problem in which the method outputs null instead of returning the (n+1)th item of the list. Is there anything that I'm overlooking .
public static ListElement getItem(ListElement head, int n){
if(n == 0){
return head;
}else if(head == null){
return null;
}else{
return getItem(head.getNext(),n+1);
}
}
This code doesn't make sense. If head is not null, it will call getItem(head.getNext(), n+1) but eventually, head will equal null (and n will never go to 0) and therefore it will return you null. Maybe you meant
return getItem(head.getNext(), n-1).
change from n+1 to n-1 (in order to get to the base case of the recursion, n == 0):
return getItem(head.getNext(),n-1);
You should be doing n-1, not n+1. n corresponds to the position of the element you want, and if you remove the top item in the list everything moves up down one position, not up.
Change to getItem(head.getNext(),n-1);
I have a binary tree made with the following constructor:
public Person(String name, int age, char gender, Person c1, Person c2)
where c1 is the left child and c2 is the right child.
I want to write a method that searches for a particular name within a maximum generation. So like a.depthFirstSearch(Eva, 1); where Eva is the name to search for and 1 is the maximum number of generations (or levels) I can look into.
Here's what I have:
EDIT:
public Person depthFirstSearch(String name, int maxGeneration)
{
{
Person temp;
if (maxGeneration>1){
if (this.name.equals(name)){
temp=this;
return temp;
}
else{
if (child1!=null)
temp=child1.depthFirstSearch(name, maxGeneration-1);
if (child2!=null)
temp=child1.depthFirstSearch(name, maxGeneration-1);
}
}
return null;
}
}
There's two problems here. I think depth gets reset to 0 every time the function calls itself, so I know I can either keep track of depth somewhere else or find an alternative. The other problem, I think, is that child2 is never really reached, since I return at child1. I'm not really sure how this works so if someone could explain that, that'd be great. Any suggestions for some fixes?
Also, I'm told that I have to search depth first, meaning looking into the deeper generations first. I'm not really sure what that means and how different it is from the logic I'm using in my implementation.
Since you decrement maxGeneration in each recursive call, you don't need the depth variable at all: when maxGeneration == 0 you simply don't search any more and return null.
As for your other problem, instead of directly returning the value of child1.depthFirstSearch(...), store the value in a temporary variable. If it is not null, you have found the node, so return it immediately, otherwise continue searching under child2.
Update:
It should be if (maxGeneration >= 1) ... (greater than or equal to), otherwise the last call with maxGeneration == 1 will always return null. Alternatively, you can just check for 0 and return null:
if (maxGeneration == 0)
return null;
// rest of your code
Also, you still aren't using the return value to check if the node was actually found in the left subtree or not. Right now, even if you find the node under child1, you still look under child2 and you will end up returning null, which is wrong. You need to search under child2 only if the left search returned null:
Person temp;
if (child1 != null) {
temp = child1.depthFirstSearch(name, maxGeneration-1);
if (temp != null)
return temp; // found the node, just return
}
// otherwise the following code will execute
if (child2 != null) {
temp = child2.depthFirstSearch(name, maxGeneration-1);
if (temp != null)
return temp; // found the node, just return
}
// didn't find node under either child
return null;