Deleting a Node from a Linked List - java

I'm trying to delete a given Node from a Linked List. I don't know why my code is not working. Any hints?
So I have [11,21,31,41] and they are asking me to delete the node at index 2 in this case 31. So far I have this:
public void delete (int k) {
//[ 11 21 31 41 ].delete( 2 ): expected=[ 11 21 41 ]
if (k < 0 || k >= N) throw new IllegalArgumentException ();
for(Node x = first; x != null; x = x.next) {
//deletes node
if(x.item == k){
x = x.next;
}
if(x.item <= k){
x = x.next.next;
}
}
}
Can someone tell me please why is this not working? Thank you

You could move nodes using next k times. Store a temporary int and a previous node. Decrement the temporary int each time you call next(). Once you are at 0 (the desired element), remove by setting the previous node's next pointer to x's next pointer, and then set x to null.
I think in your code you are missing the part where pointers are set.
For example:
(1) -> (2) -> (3)
To remove (2), set (1).next = (3) and (2) = null. This will get:
(1) -> (3)

There are a couple of things going wrong here, and I encourage you to work on some println debugging to better understand the issues as you develop.
Assuming the item field is the value of the Node, you're comparing that value of a Node to the index of said Node (e.g. x.item == k).
The general logic that you're going to want to follow is, "if the Node the iterator is pointing to is the next Node in my list, set my next to its next."

In your code you are comparing the value of node with the index you passed. This comparison will always have index less than value in node. Also after that you are not updating the node when you assume the code is correct.
Below code should give you the result.
public void delete (int k)
{
//[ 11 21 31 41 ].delete( 2 ): expected=[ 11 21 41 ]
if (k < 0 || k >= N) throw new IllegalArgumentException ();
int count = 0;//Assuming index starts from 0
Node prev;
for(Node x = first; x != null; x = x.next)
{
//deletes node
count++;
if(count<k)
{
prev = x;
continue;
}
else
{
prev.next = x.next;
x.next = null;
break;
}
}
if(count>k || count<k)
{
System.out.println("No element with index k");
}
}

#vase is correct saying
Assuming the item field is the value of the Node, you're comparing
that value of a Node to the index of said Node (e.g. x.item == k).
some example code that could fix this
public void delete(int k){
Node n = first;
for(int i = 0; i < k-1; i++){ // this loop finds the node right before the
n=n.next; // index to use to delete the desired index.
}
n.next = n.next.next; // delete command
}

Related

Working of multiple LinkedList object in a method

I was going through a sum on geeksforgeeks.com for adding two linked lists. And I am confused in the answer provided.
Node addTwoLists(Node first, Node second) {
Node res = null; // res is head node of the resultant list
Node prev = null;
Node temp = null;
int carry = 0, sum;
while (first != null || second != null) //while both lists exist
{
// Calculate value of next digit in resultant list.
// The next digit is sum of following things
// (i) Carry
// (ii) Next digit of first list (if there is a next digit)
// (ii) Next digit of second list (if there is a next digit)
sum = carry + (first != null ? first.data : 0)
+ (second != null ? second.data : 0);
// update carry for next calulation
carry = (sum >= 10) ? 1 : 0;
// update sum if it is greater than 10
sum = sum % 10;
// Create a new node with sum as data
temp = new Node(sum);
// if this is the first node then set it as head of
// the resultant list
if (res == null) {
res = temp;
} else // If this is not the first node then connect it to the rest.
{
prev.next = temp;
}
// Set prev for next insertion
prev = temp;
// Move first and second pointers to next nodes
if (first != null) {
first = first.next;
}
if (second != null) {
second = second.next;
}
}
if (carry > 0) {
temp.next = new Node(carry);
}
// return head of the resultant list
return res;
}
I understand that we have created three Nodes res, prev and temp and I don't understand how each one of them are getting updated simultaneously.
if (res == null) {
res = temp;
} else // If this is not the first node then connect it to the rest.
{
prev.next = temp;
}
Like here, how the 2nd element would be added in res when we are adding it in prev.next.
And below :
if (carry > 0) {
temp.next = new Node(carry);
}
If we are adding the last element in temp, how will it reflect in res?
The code seems to be working but I am having a hard time understanding this concept.
Please help. Thanks in advance.
res, prev and temp are references to a Node. When you write something like res = tmp; it means that now res and tmp refer to the same Node instance, and any changes made to this instance using, for example, res reference will remain when you use tmp reference.
here is the same code but with additional comments to try to help explain what is happening. This code appears to be taking two head nodes from link lists where each node contain a single digit, then adding the digits together to create a new list of single digits (e.g. 1->2->3 and 5->6->7->8 with = 1+5->2+6->3+7->0+8. Note that the third set results in a carry over so the final values in the returned list would be 6->8->0->9).
Thus, this code is not adding to two link lists together, it is adding the data contained
in each of the nodes of the two lists and putting the result into a third list.
My additional comments in the code are prefixed with WCK -
Node addTwoLists(Node first, Node second) {
Node res = null; // res is head node of the resultant list
Node prev = null;
Node temp = null;
int carry = 0, sum;
while (first != null || second != null) //while both lists exist WCK actually this is While at least one of the lists exists, I believe the comment is wrong and the code is right
{
// Calculate value of next digit in resultant list.
// The next digit is sum of following things
// (i) Carry
// (ii) Next digit of first list (if there is a next digit)
// (ii) Next digit of second list (if there is a next digit)
sum = carry + (first != null ? first.data : 0)
+ (second != null ? second.data : 0);
// update carry for next calulation
carry = (sum >= 10) ? 1 : 0; // WCK - assumes sum <20; is only carrying at most 1
// update sum if it is greater than 10
sum = sum % 10;
// Create a new node with sum as data
temp = new Node(sum);
// if this is the first node then set it as head of
// the resultant list
// WCK - the first time through the loop, res will be null
// WCK - each subsequent time through the loop, the else is invoked to link the new node to the one from the previous iteration thus linking them
if (res == null) {
res = temp; //WCK - as #ardenit says, both res and temp point to the same node at this point
} else // If this is not the first node then connect it to the rest.
{
prev.next = temp;
}
// Set prev for next insertion
// WCK - now they are starting to set up for the next iteration.
// WCK - the first time through, res, prev and temp all point to the same node after this statement is executed.
prev = temp;
// Move first and second pointers to next nodes
if (first != null) {
first = first.next;
}
if (second != null) {
second = second.next;
}
// WCK - the first time through the loop, both of the lists passed in
// have been advanced to the next node in their respective lists.
// res and prev will point to the temp. As the next iteration of the loop
// starts, temp will be pointed to a new node while res and prev will
// still point to the same node created in the first iteration. As the
// second iteration executes, prev is set to point to the new temp
// where you see (prev.next = temp) and then prev is advanced to the
// this new node as well. res will not be changed again (it is only set
// once in the first iteration)
}
// WCK - now that the loop is finished, there may be a final carry value
if (carry > 0) {
temp.next = new Node(carry);
}
// return head of the resultant list
return res;
}

Solution timing out for question: build binary tree from inorder and postorder

I've been grinding leetcode recently and am perplexed on why my solution is timing out when I submit it to Leetcode.
Here is the question:
https://leetcode.com/explore/learn/card/data-structure-tree/133/conclusion/942/
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
Here is my solution that times out in one of the test cases:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder == null || inorder.length == 0) {
return null; // input error
}
if (postorder == null || postorder.length == 0) {
return null; // input error
}
if (postorder.length != inorder.length) {
return null; // input error
}
List<Integer> inOrder = new ArrayList<Integer>();
List<Integer> postOrder = new ArrayList<Integer>();
for (int i = 0; i < inorder.length; i++) {
inOrder.add(inorder[i]);
postOrder.add(postorder[i]);
}
return buildBinaryTree(inOrder, postOrder);
}
public TreeNode buildBinaryTree(List<Integer> inOrder, List<Integer> postOrder) {
boolean found = false;
int root = 0;
int rootIndex = 0;
// for given in-order scan the post-order right to left to find the root
for (int j = postOrder.size() - 1; j >= 0 && !found; j--) {
root = postOrder.get(j);
if (inOrder.contains(root)) {
rootIndex = inOrder.indexOf(root);
root = inOrder.get(rootIndex);
found = true;
break;
}
}
if (found) {
List<Integer> leftOfRoot = new ArrayList<Integer>();
List<Integer> rightOfRoot = new ArrayList<Integer>();
if (rootIndex > 0) {
leftOfRoot.addAll(inOrder.subList(0, rootIndex));
}
if ((rootIndex + 1) < inOrder.size()) {
rightOfRoot.addAll(inOrder.subList(rootIndex + 1, inOrder.size()));
}
TreeNode node = new TreeNode(root);
node.left = buildBinaryTree(leftOfRoot, postOrder);
node.right = buildBinaryTree(rightOfRoot, postOrder);
return node;
}
return null;
}
}
Can anyone help determine why this is happening? I'm thinking it is the Leetcode judge at fault here and my code is fine.
Leetcode's judge is probably OK. This code is too casual about nested linear array operations and heap allocations. Creating ArrayLists and calling contains, addAll, subList and indexOf may appear innocuous, but they should all be thought of as extremely expensive operations when inside a recursive function that spawns two child calls in every frame.
Let's unpack the code a bit:
List<Integer> inOrder = new ArrayList<Integer>();
List<Integer> postOrder = new ArrayList<Integer>();
for (int i = 0; i < inorder.length; i++) {
inOrder.add(inorder[i]);
postOrder.add(postorder[i]);
}
This is a minor up-front cost but it's an omen of things to come. We've done 2 heap allocations that weren't necessary and walked n. I'd stick to primitive arrays here--no need to allocate objects other than the result nodes. A lookup map for inOrder with value -> index pairs might be useful to allocate if you feel compelled to create a supporting data structure here.
Next, we step into buildBinaryTree. Its structure is basically:
function buildBinaryTree(root) {
// do some stuff
if (not base case reached) {
buildBinaryTree(root.left)
buildBinaryTree(root.right)
}
}
This is linear on the number of nodes in the tree, so it's important that // do some stuff is efficient, hopefully constant time. Walking n in this function would give us quadratic complexity.
Next there's
for (int j = postOrder.size() - 1; j >= 0 && !found; j--) {
root = postOrder.get(j);
if (inOrder.contains(root)) {
rootIndex = inOrder.indexOf(root);
This looks bad, but by definition the root is always the last element in a postorder traversal array, so if we keep a pointer to it, we can remove this outer loop. You can use indexOf directly and avoid the contains call since indexOf returns -1 to indicate a failed search.
The code:
if (found) {
List<Integer> leftOfRoot = new ArrayList<Integer>();
List<Integer> rightOfRoot = new ArrayList<Integer>();
does more unnecessary heap allocations for every call frame.
Here,
leftOfRoot.addAll(inOrder.subList(0, rootIndex));
Walks the list twice, once to create the sublist and again to add the entire sublist to the ArrayList. Repeat for the right subtree for two full walks on n per frame. Using start and end indices per call frame means you never need to allocate heap memory or copy anything to prepare the next call. Adjust the indices and pass a reference to the same two arrays along the entire time.
I recommend running your code with a profiler to see exactly how much time is spent copying and scanning your ArrayLists. The correct implementation should do at most one walk through one of the lists per call frame to locate root in inOrder. No array copying should be done at all.
With these modifications, you should be able to pass, although wrangling the pointers for this problem is not obvious. A hint that may help is this: recursively process the right subtree before the left.
Yes, it would be much faster with arrays. Try this:
public static TreeNode buildTree(int[] inorder, int[] postorder, int start,
int end) {
for (int i = postorder.length-1; i >= 0; --i) {
int root = postorder[i];
int index = indexOf(inorder, start, end, root);
if (index >= 0) {
TreeNode left = index == start
? null
: buildTree(inorder, postorder, start, index);
TreeNode right = index+1 == end
? null
: buildTree(inorder, postorder, index+1, end);
return new TreeNode(root, left, right);
}
}
return null;
}
private static int indexOf(int[] array, int start, int end, int value) {
for (int i = start; i < end; ++i) {
if (array[i] == value) {
return i;
}
}
return -1;
}

Java BinarySearchTree and recursion in variables

i have a problem in understanding the following:
public int sort(char[] arr, int index)
{
if(!isEmpty())
{
index = leftChild.sort(arr,index);
arr[index++] = getContent().getToken();
index = rightChild.sort(arr,index);
}
return index;
}
Why is that working but not this:
public void sort(char[] arr, int index)
{
if(!isEmpty())
{
leftChild.sort(arr,index);
arr[index++] = getContent().getToken();
rightChild.sort(arr,index);
}
}
And i also dont understand this : index = leftChild.sort(arr,index); What does this do? Can you guys pls give me examples?
Thanks for your help,
Kiimarii
One more question, i have a method that prints the longest way from the root to a leaf of the binaryTree:
public int height()
{
if ( !isEmpty() )
{
int leftHeight = leftChild.height();
int rightHeight = rightChild.height();
if ( leftHeight > rightHeight )
{
return leftHeight + 1;
} else {
return rightHeight + 1;
}
} else {
return 0;
}
}
But how can leftHeight > rightHeight be done, if no one has a value? they are both zero or something so how can he compare that? Thanks !
Your method performs an in-order traversal of a binary search tree.
The first snippet first calls leftChild.sort(arr,index), which assigns the left sub-tree to the input array. It returns the next index to be assigned.
Then you assign getContent().getToken() of the current node to the arr[index]
Then the call to rightChild.sort(arr,index) assigns the right sub-tree to the input array and the next index to be assigned is returned.
If you ignore the index returned by the recursive call (as you do in the second snippet), arr[index++] = getContent().getToken(); will always assign a value to the 0 index of the array (assuming the initial call is (sort(arr,0))).
You must assign the returned index to the local index variable in order to assign getContent().getToken() to the correct index of the array.
The key is that index is a local variable. Let's follow a really simple example:
4
/ \
2 6
/
1
// First call
(4).sort(arr, 0);
// The left child of (4) is (2)
// (Note that each 'index' here
// is a local variable.)
index = (2).sort(arr, 0);
// We've just called sort again
index = (1).sort(arr, 0)
// and again
index = (empty).sort(array, 0)
// isEmpty() is true
// so return index
return 0
<=
index = 0
// assign contents of (1) to
// arr[0] and increment 0
arr[index++] = getContent().getToken();
// Process right child of (1)
// (index returns unchanged)
index = (empty).sort(arr, 1);
return 1
<=
index = 1
...
We're now in the call to (2).sort so its contents get assigned to index 1 of the array. Can you see how the sequence will complete in order?

Quicksort Median of Three

I'm working on my Quick Sort exercise that uses a LinkedList to sort, (I know it's not efficient and really pointless, it's for class). I understand how the Quick Sort method works, as well as the median of three strategy. My code is working properly for only certain lengths however, for example.
This works fine:
7 6 5 4 3 2 1, pivot = 4
7 6 5, pivot = 6 | 3 2 1, pivot = 2
Now, for anything that isn't like that, ie.
5 4 3 2 1, pivot = 3
5 4, throws an error | 2 1 throws an error.
Here is the code that I have:
Finds the middle node in the LinkedList.
public Node findMiddleNode() {
Node node1 = first;
Node node2 = first;
while(node2.getNext() != null && node2.getNext().getNext()!= null) {
node1 = node1.getNext();
node2 = node2.getNext().getNext();
}
return node1;
}
Finds the median of the first, middle and last nodes.
public Node medianOfThree() {
Node firstNode = first;
Node lastNode = last;
Node middleNode = findMiddleNode();
if((firstNode.getData() - middleNode.getData()) * (lastNode.getData() - firstNode.getData()) >= 0) {
return firstNode;
} else if((middleNode.getData() - firstNode.getData()) * (lastNode.getData() - middleNode.getData()) >= 0) {
return middleNode;
} else {
return lastNode;
}
}
Removes the pivots from the list, this is the method which breaks.
private Node chooseAndRemovePivot() {
Node pivot = medianOfThree();
Node previous = first;
// If the pivot is the first Node.
if(previous == pivot) {
first = previous.getNext();
}
// Gets the last Node before the pivot
while(previous.getNext() != pivot) {
previous = previous.getNext();
}
previous.setNext(pivot.getNext());
pivot.setNext(null);
size--;
if (size == 0)
last = null;
return pivot;
}
Can anyone point out what's going wrong here, I'm sure it's a simple mistake that I am making.
EDIT: Solution;
In the method chooseAndRemovePivot();
// If the pivot is the first Node.
if(previous == pivot) {
first = previous.getNext();
} else {
// Gets the last Node before the pivot
while(previous.getNext() != pivot) {
previous = previous.getNext();
}
}
This gets it working for all lengths.
The medianOfThree function will return pivot == first for lists of length 2. Thus this code:
// Gets the last Node before the pivot
while(previous.getNext() != pivot) {
previous = previous.getNext();
}
...will never find the terminal condition and instead assign previous = null when it reaches the end of the list. Then the next iteration will throw a NullPointerException.
I beleive the error is in your findMiddleNode() function. Specifically, node2.getNext.getNext() doesn't ever check that node2.getNext() is not null
in a list with an even number of items, node2.getNext().getNext() will run off the end. effectively reducing the statement to Null.getNext() which is an error.
For example using the list
first -> a -> b -> null
First node1 and node2 are set to "first.
Then node1 becomes a, and node2 becomes b.
Then node1 becomes b and node2 becomes b.getNext().getNext() or in other words Null.getNext.
The algorithm works for odd length lists, because node2.getNext().getNext() will always land on the null

Find node N in a tree

I am having trouble coding in Java the following method
int findNodeN(Node node, int n)
For example if the binary search tree is constructed as following:
20
10 30
1 14 25 35
Then node 1 would be returned if n=0, node 10 would be returned if n = 1 and so on (i.e inOrder traversal)
Appreciate any help
The simplest realization is to set counter variable to zero. Walk the tree in the usual order. When you go to right child - increase the counter, when you go to the parent and you were in the left child - increase the counter. When the counter becomes equal to N return current vertex.
Here's a version I have, it's a bit different from what you need, but it's something to work from:
public E findElement(E element)
{
TreeNode<E> current = root;
while (current != null)
{
if ( element.compareTo(current.getElement() ) == 0) //If found
{
return current.getElement();
}
else if( element.compareTo(current.getElement() ) < 0) //If element is less
{
current = current.getLeftChild(); //Try the left child
}
else //If element is greater
{
current = current.getRightChild(); //Try the right child
}
}
//not found
return null;
}
Pretty sure you can use recursion to get some more concise code, but this gets the job done.
EDIT: OK, try something like this:
public int findNodeN(Node node, int n, int callNumber) //Call initially with findNodeN(tree.getRoot(), n, 0)
{
if (node.hasLeft())
findNodeN(node.getLeftChild(), n, callNumber);
if (callNumber == n)
return node.getElement();
else
callNumber++;
if (node.hasRight())
printTreeInOrder(node.getRightChild(), n, callNumber);
}
This isn't tested.
Calum

Categories