Deleting nodes greater than specified value from linked list - algorithm

Given an integer value and a pointer to the head of the linked list, how to delete all the nodes from the list that are greater than the specified value?
e.g.
List : 10->34->11->19->26->55->17
value: 19
output: 10->11->17 (All the nodes greater than 19 needs to be removed)
(Edge case)
List : 10->3->17->5->2->14->7
value: 9
output: 3->5->2->7 (All the nodes greater than 9 needs to be removed)
I am not looking for the exact code but just an algorithm to solve this!

private static Node removeNodes(Node start, int x) {
if(start == null) return start;
if(start.data > x && start.next == null) return null;
//find first head node
Node cur = start;
Node prev = null;
//4,5,3,2,1,6 --- where x = 2
while(cur != null && cur.data > x) {
prev = cur;
cur = cur.next;
}
if(prev != null) prev.next = null;
Node newHead = cur;
while(cur.next != null) {
if(cur.next.data > x) {
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
return newHead;
}

first assign a temporary node to the start node
Then you have three cases in linked list..
if the desired node at the first position then make start to be equal start->next and delete temp node
if it is in the middle make another node to be stopped right before temp and make the next of that node to be equal the next of temp and then delete temp
if it is at last position make the next of the node before it to be equal to nullptr and that is it.

It can be solved using two pointers, previous and current,I guess this solution work.
public static ListNode removeNode(ListNode head,int value){
//removing every element whose Node value is greter than given value
if(head==null) { return head;}
ListNode current=head;
ListNode previous=new ListNode(0);
previous.next=current;
while(current!=null){
//System.out.println("current value; "+current.val);
if(current.val>=value){
if(current.next==null){
current=null;
}
else {
current=current.next;}
previous.next=current;
}
else {
previous=previous.next;
current=current.next;
}
}
return head;
}

Consider the picture here .Suppose we have to delete the node which is greater than 8 and we have Head Pointer pointing to head of the list.First we will take two pointers Prev and temp both points to head initially.Then through the pointer we will traverse the list and keep track the current and prev pointers in temp and Prev.If current number is greater than 8 Prev will point to the next node pointed by temp and temp node will be deleted.By traversing all the node and following this rule you can delete the specified node of the list....
I hope you got the point........

Related

Linked List - Keeping track of each node

I found an algorithm to loop through a sorted linked list and remove the duplicate. I wrote it, it works.
Still, I don't understand how can this work. In the end of the loop, to move forward into the while loop, we do this :
currentNode = nextNode
How can this not erase the current node ? Why does the linked list is still here ? It feels every node is erased each time by the next, isn't it ?
class LinkedList {
constructor(value) {
this.value = value;
this.next = null;
}
}
function removeDuplicatesFromLinkedList(linkedList) {
let currentNode = linkedList;
while(currentNode !== null){
let nextNode = currentNode.next;
while(nextNode !== null && nextNode.value === currentNode.value){
nextNode = nextNode.next;
}
currentNode.next = nextNode
currentNode= nextNode
}
currentNode = linkedList;
return linkedList;
}
exports.LinkedList = LinkedList;
exports.removeDuplicatesFromLinkedList = removeDuplicatesFromLinkedList;
In fact, linkedList is never overwritten, so the initial list isn't damaged (because when removing duplicates, the first one is kept, only the following are removed).
Then, currNode is just the current pointer, to the current node. Assign a new value to it don't delete the previous node, since it's still referenced through the list head linkedList.
What is really missing is the free instruction on deleted node - this algo rely on a garbage collector to work without a memory leak.
Let's do this by an example:
2 -> 3 -> 3 -> 4
Initially currentNode == 2. In the first iteration of the loop nextNode == 3, which is the next node to current node. The inner while loop doesn't run since currentNode.value isn't equal to nextNode.value. So we hit:
currentNode.next = nextNode
currentNode= nextNode
This sets the next node of currentNode to NextNode. So, nothing changes. Then we move current node one forward: currentNode = nextNode
In the next iteration though, nextNode == 3, while currentNode == 3 too. Now the inner while loop runs one iteration and moves nextNode to 4 and breaks since they aren't equal anymore. Then, currentNode.next is set to nextNode, which was 4, and after nextNode is assigned to currentNode.
Since these are all pointers to nodes, nothing is being erased. Just the duplicate values are removed from the chain of linked nodes.

Why do I need to make 'head' equal to 'prev' to finish reversing a Linked List?

sorry for the awkward question title. I don't really know how to explain without a code example. I have implemented a Linked List using generics, and I am trying to reverse it.
public Node<T> reverse() {
Node<T> prev = null;
while (head != null) {
Node<T> next = head.next;
head.next = prev;
prev = head;
head = next;
System.out.println("head: " + head.next + "\nprev: " + prev.next);
}
head = prev;
return prev;
}
head = prev;
My question is, why is this required?
My LinkedList outputs:
[output]
But without the head = prev; line it simply outputs blank []. Is this something to do with generics?
No, It has nothing to do with generics, Looking at your reverse method, initially, there are three nodes prev pointing to null, head pointing to start of the linked list, and next pointing to head's next node. At each step you are moving each node in forward direction until it is reversed, so after completion, your prev node will point to the tail of the linked list which is in fact the start of the reversed linked list, and both head and next pointing to null. So head = prev is needed to make the head point to the starting node of the reversed linked list.
*TLDR; Because at end of while loop, 'head' points to null, not the reversed list.
--
Let’s understand your code by an example:
List: 3 -> 6 -> 9 -> null
head points to 3.
// 1
Node<T> prev = null;
while(head != null) // true
Node<T> next = head.next; // next -> 6, as head.next points to Node with element 6
head.next = prev; // head->next = null, earlier it pointed to Node with element 6, prev is null
prev = head;
head = next;
Current state:
null <- 3 6 -> 9 -> null
Now, prev points to 3, head points to 6.
// 2
while(head != null) // true
Node<T> next = head.next; // next -> 9, as head.next points to Node with element 9
head.next = prev; // head->next =3, earlier it pointed to Node with element 9, prev is 3
prev = head;
head = next;
Current state:
null <- 3 <- 6 9 -> null
Now, prev points to 6, head points to 9.
// 3
while(head != null) // true
Node<T> next = head.next; // next -> null, as head.next points to null
head.next = prev; // head->next =6, earlier it pointed to null, prev is 6
prev = head;
head = next;
Current state:
null <- 3 <- 6 <- 9
Now, prev points to 9, head points to null.
// 4
while(head != null) // false
Now, head points to null and you need to return reversed linked list.
head = prev; // prev points to the node with element 9.
// null <- 3 <- 6 <- 9 <- prev (or head) as head and prev are equal.
return prev; // will return the reversed linked list.
return head; // will return the reversed linked list as both prev and head are equal.

Find the maximum sum of first and last element of a linked list

Given a singly linked list where each element contains a number and a pointer to the head of the list. Sum the first and last data and remove these nodes. Then sum the first and last data of the resulting linked list and remove these two nodes.
Keep doing this till the list becomes empty.
we have to find the maximum sum obtained from the resulting sum in O(1) space complexity.
The list is a singly linked list with even nodes.
My Thoughts:
One approach is to move the pointer to the last element at each iteration, remove the nodes, and keep a maxSum variable. This probably won't be an efficient solution.
If I understood correctly, a node in this linked list has two pointers: a pointer to the next node and one to the first node in the list.
There are several ways to solve this. Here is one:
Walk through the list and change the head pointer in each node to reference the previous node: this will give you a doubly linked list. Retain a pointer to the last node.
Now you can do a traversal in tandem starting at both ends of the list and walking towards each other.
Deleting nodes during that traversal is not really required. You could even restore the list to what it was originally in the second step.
It is even possible to do this without this extra head pointer in each node. In that case reverse the second half of the list.
Here is an implementation of the first idea, in JavaScript:
class Node {
constructor(data, head) {
this.data = data;
this.head = head || this; // default is node itself
this.next = null;
}
}
function createList(...values) {
if (!values) return null;
let head = new Node(values.shift()); // First value
let tail = head;
for (let value of values) { // Remaining values
tail.next = new Node(value, head);
tail = tail.next;
}
return tail.head;
}
function maxPairSum(head) {
if (!head) return -Infinity;
// Make doubly linked list, (ab)using node's head member
let tail;
for (tail = head; tail.next; tail = tail.next) {
tail.next.head = tail; // Next gets reference to previous
}
// Tandem walk, towards center
let maxSum = -Infinity;
for (let curr = head; curr != tail && curr != tail.next; curr = curr.next) {
maxSum = Math.max(maxSum, curr.data + tail.data);
tail = tail.head; // Is actually a reference to previous
}
// Restore head references (optional)
for (let curr = head; curr; curr = curr.next) {
curr.head = head;
}
return maxSum;
}
// Example run
let head = createList(2, 5, 1, 5, 4, 6);
let maxSum = maxPairSum(head);
console.log(maxSum); // 9
... And if you want to really remove the list, just clear the head reference. In JavaScript the garbage collector will free the unreachable memory; in some other languages (like C) you'll need to explicitly free the memory occupied by each node, before clearing the reference to the head node.
private static int max = 0, count = 0;
private static LinkedList top;
static int maximumPagesRec(LinkedList tail) {
if(tail.next==null)
max = max<top.data + tail.data ?top.data + tail.data: max;
else if(tail == top && count++ !=0){
max = max<top.data ?tail.data: max;
}
else if(top.next == tail && count++!=1)
max = max<top.data + tail.data ?top.data + tail.data: max;
else {
maximumPagesRec(tail.next);
}
top = top.next;
return max;
}
static int maximumPages(LinkedList head)
{ top = head;
return maximumPagesRec(head);
}
how about pushing all linked list value element to a stack, take 1->2->3->4 for example, and the stack will be 1234.
after that, we sum one by one and delete each linked list, store maximum value we got.

How would you get the nth node from the tail in a singly linked list (in one traverse)?

So I got this question from an exam.
How would you get the nth node from the tail in a singly linked list?
Each Node has a value and a next (which is a pointer to the next value). We are given this:
getNodeFromTail(Node head, int x) {
}
So the way I did it is to find the length of the list by traversing it once. Then going again to get the (length - x) node. So in total, 2 traversals.
getNodeFromTail(Node head, int x) {
int length = 0;
Node headdupe = head;
while (headdupe.next != NULL) {
headdupe = headdupe.next;
length++;
}
int a = length--;
for (int y = 0; y < a; y++) {
head = head.next;
}
return head;
}
This is right, but there is also a bonus question that is asking whether we can do the same thing, but only traversing it once. I couldn't think of it during the exam, but after I thought of one way, but I'm not too sure about it.
I could make an ArrayList of length x. Then every time I run the while-loop, I would add an element to the top of the array, cascade down and kick off the last element of the array. Then when the head hits null, return the node at the array[x-1].
Is this right? Is there a better solution?
Make 2 pointers to the first node
Advance one pointer by x
Advance both pointers side by side until the one further in the list hits the end.
Your pointer further back points to the xth last element.
I would do the following:
Keep a circular buffer of size x and add the nodes to it as you traverse the list. When you reach the end of the list, the x'th one from the tail is equal to the next entry in the circular buffer.
In pseudocode:
Node getNodeFromTail(Node head, int x) {
// Circular buffer with current index of of iteration.
int[] buffer = new int[x];
int i = 0;
do {
// Place the current head in its position in the buffer and increment
// the head and the index, continuing if necessary.
buffer[i++ % x] = head;
head = head.next;
} while (head.next != NULL);
// If we haven't reached x nodes, return NULL, otherwise the next item in the
// circular buffer holds the item from x heads ago.
return (i < x) ? NULL : buffer[++i % x];
}
This solution requires an additional x in memory and is a classic example of trading runtime time for memory.
Note: what to do if the input list is smaller than x is undefined.
Maintain 2 pointers,
Advance First pointer to Nth Node from start
Now Point Second Pointer to Head
Keep Advancing Both pointers now till first reaches end
Second pointer now points to Nth from last
Extra Care in case list has less than N elements
You can do it whithout traversing twice or recursion.
See the following:
int getNodeFromTail(Node head, int position)
{
if (head == NULL)
return 0;
// 2 pointers needed
Node first = head;
Node sec = head;
for(int i = 0; i < position; i++)
sec = sec.next;
while (sec.next != NULL)
{
sec = sec.next;
first = first.next;
}
return first;
}
You don't need 2 loops which is inefficient, just use 2 pointers and a counter:
Node getNodeFromTail(Node head, int x)
{
Node p = head;
Node q = head;
int diff = 0;
while (p.next != NULL)
{
p = p.next;
if (diff >= x)
q = q.next;
else
diff++;
}
return q;
}
This is the simplest solution
static int getNodeNoStack(ListNode head, int k) {
ListNode result = head;
int count = 0;
while(head.next != null) {
if(count < k) {
count++;
} else {
result = result.next;
}
head = head.next;
}
return result.val;
}
You just need to keep the pointer "result" at distance k from head traversing the entire list till the end. Once head is at the end then the result pointer will be at the kth position from tail

PreOrder Successor of a Node in BST

I'm trying this question for sometime but couldn't figure out the algorithm. My preference is to do it iteratively. Till now, I've figure out something but not sure on some point.
Currently, My algorithm looks like:
First traverse the tree to find the node
While traversing the tree, keep track of the previous node.
if you find the node, check if left child is present then that is successor return.
if left child is not present then check if right child is present the that is successor and return.
if the node(is left to the parent) and don't have left or right child then we've saved the prev node earlier then either prev or prev's right child is the successor.
But what if the node we found is in the right to parent and don't have left or right child how to find successor of this node?
May be there are many flaws in this algorithm as still I've not understand all the cases properly. If anyone has any idea or algorithm please share.
Thanks in advance.
when you find a node in preorder, to find its successor is just travesing to its next node.
what I was thinking first is the relationship of a node and its successor's values in pre-oder, but I found that it seems not very clear like the relationship in in-order. I think there is only one step beteen a node and its successor(if exists) : just move on travesing. So I design this algorithm.
my algorithm below is based on preorder travesal, it can run on a binary tree,not only BST.
#define NOT_FOUND -1
#define NEXT 0
#define FOUND 1
struct node {
struct node *p;//parent,but useless here
struct node *l;//left child
struct node *r;//right child
int value;
};
int travese(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
else
{
if(*flag == FOUND)
//when the successor is found,do pruning.
return 1;
else if(*flag == NEXT) {
printf("successor:%d\n",bnode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && bnode->value == value)
*flag = NEXT;
travese(bnode->l,flag,value);
travese(bnode->r,flag,value);
}
return 0;
}
and use it by:
int flag = NOT_FOUND;
travese(root,&flag,value);
if(flag == NEXT || flag == NOT_FOUND)
printf("no successor.\n");
EDIT:
turning a recurrence algorithm to a iterative one is not difficult by using a stack like below:
int preorder_travese_with_stack(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
struct stack s;//some kind of implement
push(s,bnode);
while(NotEmpty(s) && *flag) {
struct node *curNode = pop(s);
if(*flag == NEXT) {
printf("successor:%d\n",curNode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && curNode->value == value)
*flag = NEXT;
push(s,curNode->r);
push(s,curNode->l);
}
return 0;
}
but according to your comment and original description, I think the one you want is iterative algorithm without a stack.here it is.
After thinking ,searching and trying, I wrote one. When travse the tree iteratively without stack , the parent of a node is not useless any more. In a path, some nodes is visited not only once, and you need to record its direction at that time.
int preorder_travese_without_stack(struct node *root,int value,int *flag)
{
int state=1;
//state: traveral direction on a node
//1 for going down
//2 for going up from its left chlid
//3 for going up from its right child
struct node *cur = root;
while(1) {
if(state == 1) //first visit
{
//common travese:
//printf("%d ",cur->value);
if(cur->value == value && *flag == NOT_FOUND)
*flag = NEXT;
else if (*flag==NEXT) {
*flag = FOUND;
printf("successor:%d\n",cur->value);
break;
}
}
if((state == 1)&&(cur->l!=NULL))
cur = cur->l;
else if((state==1)&&(cur->l==NULL))
{
state = 2;
continue;
}
else if(state==2) {
if(cur->r != NULL ) {
cur=cur->r;
state = 1;
}
else
{
if(cur->p!=NULL)
{
if(cur==cur->p->r)
state = 3;
//else state keeps 2
cur=cur->p;
}
else //cur->p==NULL
{
if(cur->p->r!=NULL)
{
cur=cur->p->r;
state = 1;
}
else
break;
//end up in lchild of root
//because root's rchild is NULL
}
}
continue;
}
else //state ==3
{
if(cur->p!=NULL)
{
if(cur==cur->p->l)
state = 2;
else
state = 3;
cur=cur->p;
continue;
}
else
break;
}
}
}
the usage is the same as the first recurrence one.
If you are confused yet,mostly about the direction of a node , you can draw a tree and draw the path of pre-order traverse on paper,it would help.
I'm not sure there are bugs left in the code,but it works well on the tree below:
0
/ \
1 2
/ \ / \
3 4 5 6
btw,"wirte down pre-order (or else) travese algorithm of a tree both by recurrence and iteration" is a common interview problem, although solving the latter by a stack is permitted.but I think the BST requirement is unnecessary in pre-order travese.
My implementation of the algorithm does not use the key. Therefore it is possible to use it in any kind of binary tree, not only in Binary search trees.
The algorith I used is this:
if given node is not present, return NULL
if node has left child, return left child
if node has right child, return right child
return right child of the closest ancestor whose right child is present and not yet processed
Bellow there is my solution.
TreeNode<ItemType>* CBinaryTree<ItemType>::succesorPreOrder(TreeNode<ItemType> *wStartNode)
{
//if given node is not present, return NULL
if (wStartNode == NULL) return NULL;
/* if node has left child, return left child */
if (wStartNode->left != NULL) return wStartNode->left;
/* if node has right child, return right child */
if (wStartNode->right != NULL) return wStartNode->right;
/* if node isLeaf
return right child of the closest ancestor whose right child is present and not yet processed*/
if (isLeaf(wStartNode)) {
TreeNode<ItemType> *cur = wStartNode;
TreeNode<ItemType> *y = wStartNode->parent;
while (y->right == NULL && y->parent!=NULL){
cur = y;
y = y->parent;
}
while (y != NULL && cur == y->right) {
cur = y;
y = y->parent;
}
return y->right;
}
}
bool CBinaryTree<ItemType>::isLeaf(TreeNode<ItemType> *wStartNode){
if (wStartNode->left == NULL && wStartNode->right == NULL) return true;
else return false;
};

Resources