I'm trying to add a node in a circular list in Java. The problem is that my list has only a head (without a tail). Here is my code:
import java.io.PrintStream;
import java.util.EmptyStackException;
public class CircularList {
private Node head = null;
private class Node {
public Node(String payload, Node prev, Node next) {
super();
this.payload = payload;
this.prev = prev;
this.next = next;
}
private Node prev;
private Node next;
String payload = "";
}
public void push(String payload) {
Node n = new Node(payload, null, null);
if (isEmpty()) {
head = n;
n.next = n;
} else {
n.prev = head;
n.next = head;
}
}
Lets take some nodes.
< H - < A - < B -
This describes the connections of the nodes. A.next == H and A.prev == B.
H and B are special cases, where H is the head and B is the tail. Since the list is circular. Then H.next == B and B.prev == H.
When we push a node.
< N - < H - < A - < B -
Then we can see all of the assignments that need to change.
H = head;
B = H.next; // get the tail since you only have the head.
H.next = N;
N.prev = H;
N.next = B;
B.prev = N;
head = N;
You're almost there. When the list is empty, that part works fine. But when the list is not empty, think through what needs to happen, which is 4 things:
The 'head's previous node needs to become the new node.
The new node's 'next' needs to point at head.
The new node's 'previous' needs to point at what used to be head.prev.
What used to be head.prev's next pointer needs to point at the new node.
You'll need some temp variables to take care of all of that.
Related
Given input (items = 6, position = 3)
creates a row of 6 items and a character positioned on item 3 {0,1,2,[3],4,5}
A call to left() moves the character two positions to the left and the item at position 3 is removed {0,[1],2,4,5}
The next call to right() moves the character two positions to the right and the item at position 1 is removed {0,2,[4],5}
Then calling position() method now should return 4.
The character will not move to the left or right if no items are present so no need to implement that.
public class MyClass {
int position;
int[] items;
public MyClass(int n, int position) {
this.position = position;
items = new int[n];
for(int i=0; i<n; i++) {
items[i] = i;
}
}
}
public void left() {
int p = this.position;
items[p] = -1;
for(int z=0; z<2;) {
p--;
int value = arr[p];
if(value != -1) {
z++;
}
}
this.position = p;
}
public void right() {
int p = this.position;
items[p] = -1;
for(int z=0; z<2;) {
p++;
int value = arr[p];
if(value != -1) {
z++;
}
}
this.position = p;
}
public int position() {
return arr[position];
}
This code works perfectly for small inputs, but I am getting performance errors when the input is large.
How to implement this efficiently? I don't have test case details for the error related to performance errors.
As it already has been pointed outed both in the comments and the answer by #AbhinavMathur, in order to improve performance you need to implement Doubly linked list data structure.
Note that it's mandatory to create your own implementation that will maintain a reference to the current node. Attempt to utilize an implementation built-in in the JDK in place of the items array will not buy you anything because the advantage of the fast deletion will be nullified by the cost of iteration (in order to reach the element at position n, LinkedList needs to crawl through the n elements starting from the head, and this operation has a liner time complexity).
Methods left(), right() and position() will have the following outcome:
left() - in case when the previous node (denoted as prev in the code) associated with current is not null, and in tern its previous node exists, the current node will be dereferenced (i.e. next and previous nodes associated with the current node will be linked with each other), and the variable current would be assigned to the prev of the previous node, i.e. current.prev.prev. Time complexity O(1).
right() - in case when the next node (denoted as next in the code) associated with current is not null, and in tern its next node exists, the current node will be dereferenced in a way that has been described above, and the variable current would be assigned to the next of the next node, i.e. current.next.next. Time complexity O(1).
position() - will return a value of the current node. Time complexity O(1).
That's how it might look like:
public class MyClass {
private Node current; // a replacement for both position and items fields
public MyClass(int n, int position) {
Node current = new Node(0, null, null); // initialing the head node
if (position == 0) {
this.current = current;
}
for (int i = 1; i < n; i++) { // initialing the rest past of the linked list
Node nextNode = new Node(i, current, null);
current.setNext(nextNode);
current = nextNode;
if (position == i) {
this.current = current;
}
}
}
public void left() { // removes the current node and sets the current to the node 2 position to the left (`prev` of the `prev` node)
if (current.prev == null || current.prev.prev == null) {
return;
}
Node prev = current.prev;
Node next = current.next;
prev.setNext(next);
next.setPrev(prev);
this.current = prev.prev;
}
public void right() { // removes the current node and sets the current to the node 2 position to the right (`next` of the `next` node)
if (current.next == null || current.next.next == null) {
return;
}
Node prev = current.prev;
Node next = current.next;
prev.setNext(next);
next.setPrev(prev);
this.current = next.next;
}
public int position() {
return current.getValue();
}
public static class Node {
private int value;
private Node prev;
private Node next;
public Node(int value, Node prev, Node next) {
this.value = value;
this.prev = prev;
this.next = next;
}
// getters and setters
}
}
A link to Online Demo
Using an array, you're setting the "removed" elements as -1; repeatedly skipping them in each traversal causes the performance penalty.
Instead of an array, use a doubly linked list. Each removal can be easily done in O(1) time, and each left/right operation would only require shifting the current pointer by 2 nodes.
Im trying to create a Binary search tree that includes all numbers from 1 to n. an example would be from 1 to 5 would be something like
root: 3
root.left: 2
root.left.left = 1
root.right = 4
root.right.right = 5
This tree happens to be not very balanced, but I would prefer a method that produces as balanced of a tree as possible.
I am trying to create my own data structure for this, so I basically just wrote a Node class:
private class BinaryNode{
int data;
BinaryNode left;
BinaryNode right;
BinaryNode parent;
}
And I planned on having that inside another class, which represents the tree itself. I am stuck finding a good way determine the left/right values appropriately to build the tree, any help is appreciated!
The data on the root node would be (n+1)/2; if you've got a subtree representing the range [i..j], the root of that subtree is (i+j)/2 (using integer arithmetic).
You can build the tree recursively using that fact:
static BinaryNode build(int i, int j) {
if (i > j) return null;
int mid = (i + j) / 2; // Assumes i >= 0.
BinaryNode node = new BinaryNode();
node.data = mid;
node.left = build(i, mid - 1);
if (node.left != null) node.left.parent = node;
node.right = build(mid + 1, j);
if (node.right != null) node.right.parent = node;
return node;
}
Then start the recursive call:
BinaryNode node = build(1, n);
It must be pointed out, however, that such a binary search tree (storing contiguous integers from 1 to n) is useless: you may as well simply use an array, and "search" it using an array index.
public void insert(int id){
Node newNode = new Node(id);
if(root==null){
root = newNode;
return;
}
Node current = root;
Node parent = null;
while(true){
parent = current;
if(id<current.data){
current = current.left;
if(current==null){
parent.left = newNode;
newNode.parent = parent;
return;
}
}else{
current = current.right;
if(current==null){
parent.right = newNode;
newNode.parent = parent;
return;
}
}
}
}
Without recursion insertion of 1 to n numbers.
public static void main(String arg[]){
Solution2 s = new Solution2();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 1;i <= n;i++){
s.insert(i);
}
}
Please take a look at the following code and let me know what's wrong with it? I'm trying to insert a node at a given specific position in a linked list. We need to return the reference to the head node after inserting it.
Node InsertNth(Node head, int data, int position) {
Node newNode = new Node();
newNode.data = data;
if(head==null){
newNode.next = head;
return newNode;
}
Node first = head;
while(position > 0 && head.next!=null){
head = head.next;
position -= 1;
}
newNode.next = head;
head = newNode;
return first;
}
Yeah, there is something wrong. After the while loop, you are trying to insert newNode BEFORE head, but this does not work. The line head=newNode; is useless.
Either you need another pointer to point to the node before head, so that you can insert newNode between these two pointers, or you need to stop the while loop one step before, and insert newNode AFTER head. Here is the second solution:
while(position > 1 && head.next!=null){ //0 is replaced by 1 here
head = head.next;
position -= 1;
}
newNode.next = head.next;
head.next = newNode;
return first;
[EDIT]
In this solution, you need to handle the special case when position equals 0 by adding the following code just before the while loop:
if(position==0) {
newNode.next = head.next;
return newNode;
}
I need some help understanding how a method works.
I have a basic Node class defined like this:
class Node {
Node next = null;
int data;
public Node(int d){
data = d;
}
}
Now I'm looking at how this deleteDuplicates method is working. I understand that we are passing through each node iteratively and storing its value in a set. If the value is already in the set, I believe we are setting the previous node's next pointer to skip the current node. Here's the method:
public static Node deleteDuplicates(Node head){
Node n = head;
HashSet<Integer> set = new HashSet<Integer>();
Node previous = null;
while(n != null) {
if (set.contains(n.data)){
// skip this node
previous.next = n.next;
}
else {
set.add(n.data);
previous = n;
}
n = n.next;
}
return head;
}
I'm confused about the variables previous and n. When we set previous = n;, isn't that making them reference the same object? If they reference the same object, one change you make to n will be the same in previous. So how does the line previous.next = n.next; work?
Thanks!
read these 2 lines together,
previous = n;
n = n.next;
So, once a node is processed, the pointers for previous and n are moved forward. n is next node after previous, thus previous is set to n, and n is moved to its next node, which is n.next
For the deletion part, hope the diagram below helps
So I have a homework question where I'm supposed to use a recursive method to "find the minimum element within a subtree rooted at the specified node"
And then I'm given this as my starting point:
public TreeNode
{
int data;
TreeNode left;
TreeNode right;
}
and
/**
Finds the minimum value for the subtree that is
rooted at a given node
#param n The root of the subtree
#return The minimum value
PRECONDITION: n is not null.
*/
int min(TreeNode n)
{
// COMPLETE THE BODY OF THIS METHOD
}
Now, I've got a very basic driver program written to insert nodes into the tree and I've written my recursive method, but it seems to be counting up instead of down, here's my method:
int min(TreeNode n){
if(n.left != null) {
n = n.left;
min(n);
System.out.println("N is now " + n.value);
}
return n.value;
}
Output of my code:
Building tree with rootvalue 25
=================================
Inserted 11 to left of node 25
Inserted 15 to right of node 11
Inserted 16 to right of node 15
Inserted 23 to right of node 16
Inserted 79 to right of node 25
Inserted 5 to left of node 11
Inserted 4 to left of node 5
Inserted 2 to left of node 4
Root is 25
N is now 2
N is now 4
N is now 5
N is now 11
The minimum integer in the given nodes subtree is: 11
Can someone please explain to me why this doesn't work?
Note: this is all assuming you're in a Binary Search Tree, so returning the minimum element means returning the left-most element.
This means your recursive call is quite simple:
min(node):
if this node has a left node:
return min(node.left)
if this node does not have a left node:
return this node's value
The logic is that if we don't have another left node then we are the left-most node, so we are the minimum value.
Now, in Java:
int min(TreeNode n){
if (n.left == null)
return n.value;
return min(n.left); // n.left cannot be null here
}
Now to explain your results, consider how this method works. It calls the method on the next node (min(n.left)) before continuing. In your case you had a println after this recursive call. Therefore the println inside the recursive call went first. So your prints started at the bottom of the tree and worked their way back up. This explains the "reverse order" printing.
Your method then returned 11 as your result because (as another answer has explained) your n = n.left didn't affect any of your recursive sub-calls, only the one in the current function call. This means you returned the left node of the root, rather than the furthest left child.
I hope this makes sense. If you need clarification on anything leave a comment or something. Recursion can be quite tricky to get your head around at first.
The issue is that Java is call-by-value, not by reference -- although references are passed by value. But what that really means in this case is that the call to min(n) does not change what the variable n refers to -- it doesn't do anything at all. What you should probably be doing is return min(n).
public static void main(String[] args) throws IOException, NoSuchMethodException, InitializationError {
Logger.getRootLogger().addAppender(new ConsoleAppender(new SimpleLayout(), "System.out"));
Logger.getRootLogger().setLevel(Level.ALL);
TreeNode n1 = new TreeNode();
TreeNode n2 = new TreeNode();
TreeNode n3 = new TreeNode();
TreeNode n4 = new TreeNode();
TreeNode n5 = new TreeNode();
TreeNode n6 = new TreeNode();
n1.data = 110;
n1.left = n2;
n1.right = n3;
n2.data = 15;
n2.left = n4;
n2.right = null;
n3.data = 3;
n3.left = null;
n3.right = null;
n4.data = 4;
n4.left = null;
n4.right = n5;
n5.data = 12;
n5.left = n6;
n5.right = null;
n6.data = 19;
n6.left = null;
n6.right = null;
System.out.print("min=" + min(n1));
}
static public class TreeNode {
int data;
TreeNode left;
TreeNode right;
}
static int min(TreeNode n) {
return min(n, n.data);
}
static int min(TreeNode n, int min) {
System.out.println("N is now " + n.data);
int currentMin = min;
if (n.left != null && n.right != null) {
final int left = min(n.left);
final int right = min(n.right);
if (left < right) {
currentMin = left;
} else {
currentMin = right;
}
} else if (n.left != null) {
currentMin = min(n.left);
} else if (n.right != null) {
currentMin = min(n.right);
}
if (currentMin < min) {
return currentMin;
} else {
return min;
}
}
OUTPUT is:
N is now 110
N is now 15
N is now 4
N is now 12
N is now 19
N is now 3
min=3
You need to use some tree traversal algoritm, for checking every node of the tree. Also you need to store current finded minimum. Pass this minimum into recursive function. It is calling "accumulator".
The last statement in your method implementation returns the node n's value. As n starts with the root and is replaced by its left child (if exists) you always get the value of the root's left child.
The following code should do it:
int min(final Tree n){
int result;
if(n == null){
result = Integer.MAX_VALUE;
} else {
result = n.value;
final int leftResult = min(n.left);
if(leftResult < result){
result = leftResult;
}
final int rightResult = min(n.right);
if(rightResult < result){
result = rightResult;
}
}
return result;
}
Or you could use the Visitor pattern (you would need to make your tree Iterable then and pass the values to the Visitor one-by-one):
interface TreeVisitor {
void accept(int value);
}
class MinTreeVisistor implements TreeVisitor {
int min = Integer.MAX_VALUE;
#Override
public void accept(int value) {
if(value < this.min) {
this.min = value;
}
}
}