I am given the pointer to the head node of a sorted doubly linked list and an integer to insert into the list.I am told to create a node and insert it into the appropriate position in the list such that its sorted order is maintained. The head node might be NULL.
Sample Input
NULL , data = 2
NULL <-- 2 <--> 4 <--> 6 --> NULL , data = 5
Sample Output
NULL <-- 2 --> NULL
NULL <-- 2 <--> 4 <--> 5 <--> 6 --> NULL
I tried the above problem.But My program is terminating due to timeout.What am I doing wrong in the below code. Assume Node class and main function is already there. Many Thanks in advance!!
Node SortedInsert(Node head,int data) {
Node newn = new Node();
newn.data = data;
newn.prev=null;
newn.next = null;
Node ptr = head;
Node nex=head.next;
while(ptr!=null && nex!=null) {
if(ptr.data<=newn.data && nex.data>=newn.data) {
newn.next = nex;
newn.prev = ptr;
nex.prev = newn;
ptr.next = newn;
}
else {
nex=nex.next;
ptr=ptr.next;
}
}
if(ptr!=null && nex==null) {
if(ptr.data>=newn.data) {
newn.next=ptr;
ptr.prev=newn;
newn.prev=null;
head=newn;
}
else {
ptr.next=newn;
newn.prev = head;
}
}
if(head==null) {
head = newn;
}
return head;
}
Fairly simple:
You are not breaking out of the loop after succesfully inserting. Therefore it keeps looping over the position it inserts the node in. Make a tiny change:
if(ptr.data>=newn.data)
{
newn.next=ptr;
ptr.prev=newn;
newn.prev=null;
head=newn;
break;
}
However, you have some redundant code written. This is shorter and doesn't contain redundant code:
Node SortedInsert(Node head,int data) {
Node newn = new Node();
newn.data = data;
Node ptr = head;
if (ptr == null) {
head = newn;
} else if ( ptr.data > newn.data ) {
newn.next = ptr;
ptr.prev = newn;
head = newn;
} else {
Node nex = head.next;
while (nex != null && nex.data <= newn.data) {
ptr = nex;
nex = nex.next;
}
ptr.next = newn;
newn.prev = ptr;
if (nex != null) {
nex.prev = newn;
newn.next = nex;
}
}
return head;
}
If the head node is null you'll geta NullPointerException while trying to get the next/prev nodes. You should check that first:
Node sortedInsert(Node head, int data) {
Node newn = new Node();
newn.data = data;
//Basic case: the list is empty, so the head is null
if (head==null) {
return newn;
}
//If node is not null
Node aux= head;
Node auxPrev;
while (aux!=null && aux.data<data) {
auxPrev=aux;
aux=aux.next;
}
//auxPrev will be null if we are going to insert in the first position
if (auxPrev!=null)
auxPrev.next=newn;
newn.prev=auxPrev;
head=newn;
}
//aux will be null if we insert in the last position
if (aux!=null) {
aux.prev=newn;
newn.next=aux;
}
return head;
}
Related
I have the following code and in the code line where it says 't = obj.deleteNode(obj,3);', I think this should delete 4 and 5. I'm not sure why its not doing it. I also think 'head.next' is Node#788 which is attributed to the number 4. 'head' and 'n' are Node#787 because I passed in the parameter 'obj' which begins with the address Node#787.
class Node {
Node next = null;
int data;
public Node(int d) {
data = d;
Node next = null;
}
Node appendToTail(int d) {
Node end = new Node(d);
Node n = this;
while (n.next != null) {
n = n.next;
}
n.next = end;
return end;
}
Node deleteNode(Node head, int d){
if(head == null) return null;
Node n = head;
if(n.data == d){
return head.next;
}
while(n.next != null){
if(n.next.data == d){
n.next = n.next.next;
return head;
}
n = n.next;
}
return head;
}
public static void main(String[] args) {
Node t;
Node obj = new Node(3);
t = obj.appendToTail(4);
t = obj.appendToTail(5);
t = obj.deleteNode(obj,3);
for (t = obj; t != null; t = t.next) {
System.out.println(t.data);
}
}
}
///
Output:
3
4
5
///
Expected output:
3
it says t = obj.deleteNode(obj,3);, I think this should delete 4 and 5.
No, it shouldn't. Your list is 3→4→5, so deleting the node with 3 should result in 4→5. That is what deleteNode is supposed to do: it should find the node that has the given value (3 in this case), and remove only that node, making sure that the preceding node (if any) is rewired to link to the node that follows it (if any).
However, your code has some logical errors:
You shouldn't reference obj after you have deleted that node. It is still there as long as you reference it, but you should only continue with the reference that deleteNode returns.
Don't pass a node reference to the deleteNode: the head of the list is supposed to be the instance on which you call deleteNode.
Don't capture the return value of insertNode unless you have good reason to use it. This is because it returns the newly added node, not (necessarily) the head of the list.
Use meaningful variable names: replace t with `head
Here is how I would code it:
class Node {
Node next = null;
int data;
public Node(int d) {
data = d;
Node next = null;
}
Node appendToTail(int d) {
Node end = new Node(d);
Node n = this;
while (n.next != null) {
n = n.next;
}
n.next = end;
return end;
}
Node deleteNode(int d){ // <-- change parameter list
Node node = this; // Assume `this` is the head of the list
if(node.data == d){
return this.next;
}
while(node.next != null){
if(node.next.data == d){
node.next = node.next.next;
return this;
}
node = node.next;
}
return this;
}
public static void main(String[] args) {
Node head = new Node(3);
// Don't assign the return value of appendToTail to a variable.
// However, chaining can be useful
head.appendToTail(4).appendToTail(5);
// Don't pass a node as argument, but capture the return value
// to be the (new) head of the list
head = head.deleteNode(3);
for (Node node = head; node != null; node = node.next) {
System.out.println(node.data);
}
}
}
When you are trying to delete node 3 which is head node you are just returning head.next in that case which is stored in 't' but later you are looping through obj which is still pointing to node 3
try this
if(n.data == d){
head = head.next;
return head;
}
As I've just started programming a few months back a lot of new information is coming and I'm having trouble catching up.So here I have created what I thought was a sorted linked list.Turns out it is not sorted
public boolean insert(Person person) {
Node n = new Node(person);
Node p = head;
if(p == null) {
head = n;
size++;
return true;
} else {
Node temp = p;
int comparison;
while(temp.next != null) {
comparison = temp.person.name.compareTo(person.name);
if(comparison == 0){
return false;
}
temp = temp.next;
}
temp.next = n;
size++;
return true;
}
}
The method works,it inserts the persons,but they arent sorted like they should be.What part of the code do I need to change/remove in order to make it sort.
Thanks!
You should insert like this:
static boolean insert(Person person) {
Node newNode = new Node(person);
if (head == null) {
head = newNode;
size++;
return true;
}
Node current = head;
Node prev = null;
int comparison;
while (current != null) {
comparison = person.name.compareTo(current.person.name);
if (comparison == 0) {
return false;
} else if (comparison > 0) { /// greater than
if (current.next == null) { // check if reach tail of the linked list add and break
current.next = newNode;
break;
}
} else { // less then
if (prev == null) { // check if it should be first then put and break
Node oldHead = head;
head = newNode;
head.next = oldHead;
break;
}
prev.next = newNode;
newNode.next = current;
break;
}
prev = current;
current = current.next;
}
size++;
return true;
}
There is a problem in your else part. You are returning false when same value is given. But it is not interpreted properly for a valid case.
You need to have as below.
Check current node value - Check for null pointer exception
Check next node value - Check for null pointer exception
If current input is between currentNode and nextNode then do insert between.
If reaches last node, then insert at the end
// Complete the sortedInsert function below.
/*
* For your reference:
*
* DoublyLinkedListNode {
* int data;
* DoublyLinkedListNode next;
* DoublyLinkedListNode prev;
* }
*
*/
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode Leader=head;
DoublyLinkedListNode newNode = new DoublyLinkedListNode(data);
while(Leader.next!=null){
if(data>Leader.data){
Leader = Leader.next;
}
else {
if(Leader.prev == null) {
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
if(Leader.next == null) {
if(data<Leader.data) {
newNode.prev = Leader.prev;
newNode.next = Leader;
Leader.prev.next = newNode;
return head;
} else {
newNode.prev = Leader;
Leader.next = newNode;
return head;
}
}
return head;
}
in the above-sorted insert method how to decrease this doubly linked list complexity, this is a hackerrank question I'm getting timed outs for the test cases I need help in decreasing the time complexity for this code.
You code will never come out of while loop.
Lets take the example. List = [(1), (4), (4)](only 1 element). New node is (4). Your result should be [(1), (4), (4), (4)]. But lets walk your code and check what will happen. Initially Leader = (1)
while(Leader.next!=null){ // 1
if(data>Leader.data){ // 3
Leader = Leader.next;
}
else { // 6
if(Leader.prev == null) { // 7
newNode.next = Leader;
Leader.prev = newNode;
head = newNode;
return head;
}
}
}
At line 1 check will pass (as (1).next is not null; in fact it is (4)).
At line 3 ((4) > (1)). Check pass. Leader = (1).next = (4). Jump to line 1
At line 1 check will pass (as (4).next is not null; in fact it is (4)).
At line 3 ((4) > (4)). Check Fail. Enter line 7
At line 7 check will fail ((4).prev is not null; in fact it is (4) - 1st 4). No update in Leader will take place. Leader will remain same & you will enter infinte loop from here.
You will have to take care of this. Maybe the Problem's discussion page will help. But do give it a through try.
My own try is included below:
static DoublyLinkedListNode sortedInsert(DoublyLinkedListNode head, int data) {
DoublyLinkedListNode n = new DoublyLinkedListNode();
n.data = data;
DoublyLinkedListNode curr = head;
if (head == null) {
return n;
}
// if given node is smaller than 1st node
if (data < curr.data) {
n.next = curr;
return n;
}
// find first node greater than given node
while (curr.next != null && curr.data < data) {
curr = curr.next;
}
// reached to the end.
if (curr.next == null && data >= curr.data) {
curr.next = n;
} else { // found the 1st node which is greater than given node
curr.prev.next = n;
n.next = curr;
}
return head;
}
I'm trying to learn about linked list and it has been little challenging for me. I'm trying to reverse the link list with recursive method. Here is my code:
public class ListNode {
Node head = null;
int nodeCount= 0;
int counter = 0;
ListNode(){
head = null;
}
public void insertNode( String name ) {
if (head == null) {
head = new Node(name, null);
nodeCount++;
} else {
Node temp = new Node(name, null);
temp.next = head;
head = temp;
nodeCount++;
}
}
public Node reverseTest(Node L){
// Node current = new Node(null,null);
if(L == null || L.next ==null){
return L;
}
Node remainingNode = reverseTest(L.next);
Node cur = remainingNode;
while(cur.next !=null){
cur=cur.next;
}
L.next = null;
cur.next = L;
return remainingNode;
}
public static void main(String[] args){
ListNode newList = new ListNode();
newList.insertNode("First");
newList.insertNode("Second");
newList.insertNode("Third");
newList.insertNode("Fourth");
newList.reverseTest(newList.head);
}
}
The problem I'm having with is the reverse method. When the method is over it only returns the last node with the value "First".Through the entire recursion remainingNode only holds and returs value from the base case which is confusing me. I was excepting it to move further through the nodes. After the method is executed newList holds only one node with next node as null and that node is the head now. I was assuming it will reverse the linkedlist with the sequence First --> Second--> Third --> Fourth. What am I doing wrong?
Actually, everything works here. Your only problem is in your main method: you don't get the result of your method.
newList.reverseTest(newList.head);
You need to actually set the new head with the result:
newList.head = newList.reverseTest(newList.head);
This would have been easier to see if you had declared your method static:
newList.head = ListNode.reverseTest(newList.head);
As a bonus, here is a fully recursive equivalent:
public static Node reverse(Node head) {
if (head == null || head.next == null) {
return head;
}
Node newHead = reverse(head.next);
// head.next points to the new tail, we push the former head at the end
head.next.next = head;
// now head has become the new tail, we cut the end of the list
head.next = null;
return newHead;
}
I have a ordered binary tree:
4
|
|-------|
2 5
|
|-------|
1 3
The leaves point to null. I have to create a doubly link list which should look like
1<->2<->3<->4<->5
(Obviously 5 should point to 1)
The node class is as follows:
class Node {
Node left;
Node right;
int value;
public Node(int value)
{
this.value = value;
left = null;
right = null;
}
}
As you can see the doubly link list is ordered (sorted) as well.
Question: I have to create the linked list form the tree without using any extra pointers. The left pointer of the tree should be the previous pointer of the list and the right pointer of the tree should be the next pointer of the list.
What I thought off: Since the tree is an ordered tree, the inorder traversal would give me a sorted list. But while doing the inorder traversal I am not able to see, where and how to move the pointers to form a doubly linked list.
P.S I checked some variations of this question but none of them gave me any clues.
It sounds like you need a method that accepts a Node reference to the root of the tree and returns a Node reference to the head of a circular list, where no new Node objects are created. I would approach this recursively, starting with the simple tree:
2
|
|-----|
1 3
You don't say whether the tree is guaranteed to be full, so we need to allow for 1 and/or 3 being null. The following method should work for this simple tree:
Node simpleTreeToList(Node root) {
if (root == null) {
return null;
}
Node left = root.left;
Node right = root.right;
Node head;
if (left == null) {
head = root;
} else {
head = left;
left.right = root;
// root.left is already correct
}
if (right == null) {
head.left = root;
root.right = head;
} else {
head.left = right;
right.right = head;
right.left = root;
}
return head;
}
Once it is clear how this works, it isn't too hard to generalize it to a recursive method that works for any tree. It is a very similar method:
Node treeToList(Node root) {
if (root == null) {
return null;
}
Node leftTree = treeToList(root.left);
Node rightTree = treeToList(root.right);
Node head;
if (leftTree == null) {
head = root;
} else {
head = leftTree;
leftTree.left.right = root;
root.left = leftTree.left;
}
if (rightTree == null) {
head.left = root;
root.right = head;
} else {
head.left = rightTree.left;
rightTree.left.right = head;
rightTree.left = root;
root.right = rightTree;
}
return head;
}
If I got all the link assignments covered correctly, this should be all you need.
Do an in-order traversal of the list, adding each list item to the doubly linked list as you encounter it. When done, add an explicit link between the first and last items.
Update 3/6/2012: Since you must reuse the Node objects you already have, after you put the node objects into the the list, you can then iterate over the list and reset the left and right pointers of the Node objects to point to their siblings. Once that is done, you can get rid of the list and simply return the first node object.
This should also work:
NodeLL first = null;
NodeLL last = null;
private void convertToLL(NodeBST root) {
if (root == null) {
return;
}
NodeLL newNode = new NodeLL(root.data);
convertToLL(root.left);
final NodeLL l = last;
last = newNode;
if (l == null)
first = newNode;
else {
l.next = newNode;
last.prev = l;
}
convertToLL(root.right);
}
Let your recursion return the left and right end of formed list. Then you link your current node to the last of the left list, and first of the right list. Basic case it, when there is no left or right element, which is the node it self for both. Once all is done, you can link the first and last of the final result. Below is the java code.
static void convertToSortedList(TreeNode T){
TreeNode[] r = convertToSortedListHelper(T);
r[1].next = r[0];
r[0].prev= r[1];
}
static TreeNode[] convertToSortedListHelper(TreeNode T){
TreeNode[] ret = new TreeNode[2];
if (T == null) return ret;
if (T.left == null && T.right == null){
ret[0] = T;
ret[1] = T;
return ret;
}
TreeNode[] left = TreeNode.convertToSortedListHelper(T.left);
TreeNode[] right = TreeNode.convertToSortedListHelper(T.right);
if (left[1] != null) left[1].next = T;
T.prev = left[1];
T.next = right[0];
if (right[0] != null) right[0].prev = T;
ret[0] = left[0]==null? T:left[0];
ret[1] = right[1]==null? T:right[1];
return ret;
}
Add the following method to your Node class
public Node toLinked() {
Node leftmost = this, rightmost = this;
if (right != null) {
right = right.toLinked();
rightmost = right.left;
right.left = this;
}
if (left != null) {
leftmost = left.toLinked();
left = leftmost.left;
left.right = this;
}
leftmost.left = rightmost;
rightmost.right = leftmost;
return leftmost;
}
EDIT By maintaining the invariant that the list returned by toLinked() has the proper form, you can easily get the left- and rightmost nodes in the sublist returned by the recursive call on the subtrees
/* input: root of BST. Output: first node of a doubly linked sorted circular list. **Constraints**: do it in-place. */
public static Node transform(Node root){
if(root == null){
return null;
}
if(root.isLeaf()){
root.setRight(root);
root.setLeft(root);
return root;
}
Node firstLeft = transform(root.getLeft());
Node firstRight = transform(root.getRight());
Node lastLeft = firstLeft == null ? null : firstLeft.getLeft();
Node lastRight= firstRight == null ? null : firstRight.getLeft();
if(firstLeft != null){
lastLeft.setRight(root);
root.setLeft(lastLeft);
if(lastRight == null){
firstLeft.setLeft(root);
}
else{
firstLeft.setLeft(lastRight);
root.setRight(firstRight);
}
}
if(firstRight != null){
root.setRight(firstRight);
firstRight.setLeft(root);
if(lastLeft == null){
root.setLeft(lastRight);
lastRight.setLeft(root);
firstLeft = root;
}
else{
root.setLeft(lastLeft);
lastRight.setRight(firstLeft);
}
}
return firstLeft;
}