Problem: Given a value, remove all instances of that value from a linked list. More info below: JAVA
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode n = head; //1, 2, 6, 3, 4, 5, 6
while(n.next == null){
if(n.next.val == val){
n.next = n.next.next;
}
n = n.next;
if(n == null){break;}
}
return head;
}
}
Since its a pass by reference, it should be updating shouldn't it?
I tried:
removeElements([1,2,6,3,4,5,6], 6)
But it didn't remove anything. So what I am doing incorrectly?
There are a couple of issues:
you want to loop until a node is null not until is not null (i.e. while( ... != null))
you might want to loop until n is null, not until n.next is null, otherwise you'd skip the last element
you want to check for n.val == val not n.next.val == val, otherwise you'd skip the first element
if you check n you want to keep track of the previous node in case you need to remove n, i.e. prev.next = n.next.
if the first element (the head) is to be removed you need to replace the head, i.e. return the second element (this can be done by checking prev == null which would mean that n is the current head).
As mentioned by Thomas in his first point, you wrote the while loop incorrectly. Also, because you have a single linked list, you need to keep track of the previous node (also mentioned by Thomas).
public static ListNode removeElements(ListNode head, int val)
{
ListNode n = head;
ListNode prev = null; //the previous node.
while (n != null)
{
if (n.value == val)
{
//if prev is null it means that we have to delete the head
//and therefore we need to advance the head
if (prev == null)
{
head = n.next;
prev = null;//remains at null because there's nothing before head
n = head;//new head, let's start from here
} else
{
prev.next = n.next; //let's skip the element to delete
n = n.next;//let's advance to the next node
}
} else
{
//nothing to delete, let's advance to the next node and make
//the current node the previous node in the next iteration
prev = n;
n = n.next;
}
}
return head;
}
Its always a good practice to solve these questions with proper test cases. Design the possible test cases including the corner cases. Then follow your algorithm and see if it solves the problem for the test cases. Write the code and dry run it, this will do a sanity check of the code as well as of the logic.
Below are the cases for this question for which test cases must be written.
Null list,
List with one element and value being equal to the value to be deleted
List with one element and value not being equal to the value to be deleted
List with two elements and first node value being equal to the value to be deleted
List with two elements and last node value being equal to the value to be deleted
List with three elements and first node value being equal to the value to be deleted
List with three elements and second node value being equal to the value to be deleted
List with three elements and last node value being equal to the value to be deleted
Below is the code for the problem of removing nodes with a given value in a linked list.
public ListNode removeElements(ListNode head, int val) {
while(head != null && head.val == val){
head = head.next;
}
if(head == null){
return null;
}
ListNode node = head;
while(node.next != null){
if(node.next.val == val){
node.next = node.next.next;
}else{
node = node.next;
}
}
return head;
}
Related
this is my first question here. This may be a dumb question but I am having issues with understanding why the order specifically matters when reversing a linked list in this way.
So here I'm reversing a linked list, which works
ListNode prev = null, curr = head, next = head;
while (curr != null){
next = next.next;
curr.next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
which works just fine.
But why can't I do the following?
//edge cases:
if (head == null || head.next == null){
return head;
}
ListNode prev = null, curr = head, next = head.next; //change here
while (curr != null){
//line was previously here
curr.next = prev;
prev = curr;
curr = next;
next = next.next; //moved here
}
head = prev;
return head;
Why does it matter that I set next = next.next at the beginning of the while loop, rather than the end? Why can't I set next = head.next first and then iterate it at the end of the loop without getting a null pointer exception?
Just for the record, you can think of the reverse operation as popping from the input list and pushing onto the result. Less epic code results:
ListNode reverse(ListNode head) {
ListNode result = null;
while (head != null) {
ListNode elt = head; // pop into elt
head = head.next;
elt.next = result; // push elt onto result
result = elt;
}
return result;
}
When you make such a change, you change the state at which the loop condition will be verified. And this causes the issue.
In the working code, we have this loop invariant:
curr and next are equal. They are either both null or both reference the same node.
In the non-working code, this is not true, as now next is one step ahead. The corresponding loop invariant is now next == curr.next. So when curr is the tail node, next will be null. In the next iteration of the loop, next = next.next is executed, which is invalid as next was null, so this raises an exception.
It would work if you would make that statement conditional:
if (next != null) next = next.next;
Or this would also work:
if (next == null) break;
next = next.next;
But both these alternatives are not as elegant as the original code, as now there are two checks to be made in each iteration (the loop condition, and this extra check). In fact, this extra check is just the repetition of the loop condition as at that moment next and curr are equal.
I have been working on this add method for a custom linkedlist lab I am working on. I cannot figure out how to shift values over by one index, once I insert the new node. Here is my source code.
public void add(int index, Object element) throws IndexOutOfBoundsException {
if(index > size() || index < 0) {
throw new IndexOutOfBoundsException();
}
ListNode newNode = new ListNode(element, null);
if(head == null) {
head = newNode;
return;
}
ListNode nextNode = head.nextNode;
ListNode currNode = head;
int i = 0;
while(currNode!= null) {
if(index == i) {
break;
}
currNode = nextNode;
//Breaks down here with null pointer exception
nextNode = nextNode.nextNode;
}
currNode = newNode;
currNode.nextNode = nextNode;
}
It is throwing null pointer as when you are iterating last node, next node points to null. Check for next node point to null also if you have to add new node in last.
Also in your code you are not increasing the value of i always it is iterating the whole list.
I don't really know what you are trying to achieve here, and I agree with #Pritam Banerjee's comment. But an obvious problem in your code is that you are never incrementing i, so you'll never break out of your while loop and at some point you are going to hit the end of your list and nextNode.nextNode is going to be null, hence your exception. (Also note that nextNode.nextNode will be null before currNode is.)
There is a problem on leetcode called Odd Even Linked List.
It says:
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.
You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.
Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.
Here is my Node class
public class Node
{
private int value;
private Node next;
public Node(int Value)
{
this.value = Value;
this.next = null;
}
public Node()
{
this.value = -1;
this.next = null;
}
public Node getNext() {
return next;
}public void setNext(Node next) {
this.next = next;
}public int getValue() {
return value;
}public void setValue(int value) {
this.value = value;
}
}
I got 8 items in list which has values 1,2,3,4,5,6,7,8. This is my output -->1-->3-->5-->7-->2-->4-->6-->8
And here is my Linked list method to solve OddEven task.
public void oddEven()
{
if(head.getNext() == null)
return;
Node lastOdd = head.getNext(); // gets the value of last odd even in list.
Node current = lastOdd.getNext(); // Puts the reference on the first even index.
Node before = lastOdd; // This node, will always be one index before current Node
int travel = 1, loop;
while(current != null)
{
loop = travel;
// Prvo petlja putuje do sledeceg neparnog elementa
while(loop-- > 0)
{
before = current;
current = current.getNext();
}
if(current == null) // If it is end of the list, exit loop.
break;
before.setNext(current.getNext());
current.setNext(lastOdd.getNext());
lastOdd.setNext(current);
lastOdd = current;
current = before.getNext();
}
}
It works perfectly fine on my pc. But when i put code in leetcode i get the error that it doesnt work. But it is same code. Here is code from leetcode
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode oddEvenList(ListNode head)
{
if(head.next == null)
return head;
ListNode lastOdd = head.next; // gets the value of last odd even in list.
ListNode current = lastOdd.next; // Puts the reference on the first even index
ListNode before = lastOdd;
int travel = 1, loop;
while(current != null)
{
loop = travel;
// Prvo petlja putuje do sledeceg neparnog elementa
while(loop-- > 0)
{
before = current;
current = current.next;
}
if(current == null)
break;
before.next = current.next;
current.next = lastOdd.next;
lastOdd.next = current;
lastOdd = current;
current = before.next;
}
return head;
}
}
Here is the error i get
for input :[1,2,3,4,5,6,7,8]
Your answer :[1,2,4,6,8,3,5,7]
Expected answer :[1,3,5,7,2,4,6,8]
But it is same method, where did i made mistake ?
I went to the site and put your code in to make it easier to see whats going on, the issue is this line:
ListNode lastOdd = head.next; // gets the value of last odd even in list.
The first element of the list is 1, yet you are starting the last odd as being the next in the list, not the head of the list. Just changing that to:
ListNode lastOdd = head
and it provides the correct answer.
The code itself needs some tidy up, the inner while loop seems to serve no real purpose, not sure why thats there or its a left over element of a previous attempt?
What loop and travel variables are doing? They are constant at 1 in each iteration, then why while(loop-- > 0) loop. Sorry didn't get what you are trying to achieve with that loop.
int travel = 1, loop;
while(current != null)
{
loop = travel;
// Prvo petlja putuje do sledeceg neparnog elementa
while(loop-- > 0)
{
Solution: Find the last node in the list. Move all even positioned nodes to the end, by doing append. Make sure you stop at the node marked as last in first step, else it would run into infinite loop.
Working on a HW assignment. The assignment is to reverse a linked list recursively. I just don't understand why at my System.out.println(head.data) line head.data always prints as 0. Assuming I enter 4,5,6 (the fill and read methods for this work, if I put a print in my final else it will show that head is still 4, 5, 6) and head.next is null, doesn't that mean that head.data is equal to 6? I know I've got a lot of other problems going on with trying to reverse this, but I just don't understand why when head.next is null the head.data is 0. I thought head.next was the next item in the list, not the current one.
public static Node reverse(Node head)
{
Node n = new Node();
if (head == null)
{
return n;
} else if (head.next == null)
{
System.out.println(head.data);
n.data = head.data;
head.next = null;
n.next = reverse(head.next);
return n;
} else
{
reverse(head.next);
return n;
}
}
The following:
Node n = new Node();
if(head == null) {
return n;
}
results in the reverse of an empty list being a single-element list with the default value of data (presumably zero?)
Also, the final else is clearly not right, as it never does anything to n before returning it.
a linear linked list is a set of nodes. This is how a node is defined (to keep it easy we do not distinguish between node an list):
class Node{
Object data;
Node link;
public Node(Object pData, Node pLink){
this.data = pData;
this.link = pLink;
}
public String toString(){
if(this.link != null){
return this.data.toString() + this.link.toString();
}else{
return this.data.toString() ;
}
}
public void inc(){
this.data = new Integer((Integer)this.data + 1);
}
public void lappend(Node list){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = list;
}
public Node copy(){
if(this.link != null){
return new Node(new Integer((Integer)this.data), this.link.copy());
}else{
return new Node(new Integer((Integer)this.data), null);
}
}
public Node invert(){
Node child = this.link;
while(child != null){
child = child.link;
}
child.link = this;....
}
}
I am able to make a deep copy of the list. Now I want to invert the list so that the first node is the last and the last the first. The inverted list has to be a deep copy.
I started developing the invert function but I am not sure. Any Ideas?
Update: Maybe there is a recursive way since the linear linked list is a recursive data structure.
I would take the first element, iterate through the list until I get to a node that has no child and append the first element, I would repeat this for the second, third....
I sometimes ask this question in interviews...
I would not recommend using a recursive solution, or using a stack to solve this. There's no point in allocating O(n) memory for such a task.
Here's a simple O(1) solution (I didn't run it right now, so I apologize if it needs some correction).
Node reverse (Node current) {
Node prev = null;
while (current != null) {
Node nextNode = current.next;
current.next = prev;
prev = current;
current = nextNode;
}
return prev;
}
BTW: Does the lappend method works? It seems like it would always throw a NullReferenceException.
There's a great recursive solution to this problem based on the following observations:
The reverse of the empty list is the empty list.
The reverse of a singleton list is itself.
The reverse of a list of a node N followed by a list L is the reverse of the list L followed by the node N.
You can therefore implement the reverse function using pseudocode along these lines:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
appendNodeToList(node, node.next); // Append the new value.
}
A naive implementation of this algorithm runs in O(n2), since each reversal requires an append, which requires an O(n) scan over the rest of the list. However, you can actually get this working in O(n) using a clever observation. Suppose that you have a linked list that looks like this:
n1 --> n2 --> [rest of the list]
If you reverse the list beginning at n2, then you end up with this setup:
n1 [reverse of rest of the list] --> n2
| ^
+------------------------------------------+
So you can append n1 to the reverse of the rest of the list by setting n1.next.next = n1, which changes n2, the new end of the reverse list, to point at n1:
[reverse of the rest of the list] --> n2 --> n1
And you're golden! Again more pseudocode:
void reverseList(Node node) {
if (node == null) return; // Reverse of empty list is itself.
if (node.next == null) return; // Reverse of singleton list is itself.
reverseList(node.next); // Reverse the rest of the list
node.next.next = node; // Append the new value.
}
EDIT: As Ran pointed out, this uses the call stack for its storage space and thus risks a stack overflow. If you want to use an explicit stack instead, you can do so like this:
void reverseList(Node node) {
/* Make a stack of the reverse of the nodes. */
Stack<Node> s = new Stack<Node>();
for (Node curr = node; node != null; node = node.next)
s.push(curr);
/* Start unwinding it. */
Node curr = null;
while (!s.empty()) {
Node top = s.pop();
/* If there is no node in the list yet, set it to the current node. */
if (curr == null)
curr = top;
/* Otherwise, have the current node point to this next node. */
else
curr.next = top;
/* Update the current pointer to be this new node. */
curr = top;
}
}
I believe that this similarly inverts the linked list elements.
I would treat the current list as a stack (here's my pseudo code):
Node x = copyOf(list.head);
x.link = null;
foreach(node in list){
Node temp = copyOf(list.head);
temp.link = x;
x = temp;
}
At the end x will be the head of the reversed list.
I more fammiliar whit C, but still let me try. ( I just do not sure if this runs in Java, but it should)
node n = (well first one)
node prev = NULL;
node t;
while(n != NULL)
{
t = n.next;
n.next = prev;
prev = n;
n = t;
}
Reversing a single-linked list is sort of a classic question. It's answered here as well (and well answered), it does not requires recursion nor extra memory, besides a register (or 2) for reference keeping.
However to the OP, I guess it's a school project/homework and some piece of advice, if you ever get to use single linked list for some real data storage, consider using a tail node as well. (as of now single linked lists are almost extinct, HashMap buckets comes to mind, though).
Unless you have to check all the nodes for some condition during 'add', tail is quite an improvement. Below there is some code that features the reverse method and a tail node.
package t1;
public class SList {
Node head = new Node();
Node tail = head;
private static class Node{
Node link;
int data;
}
void add(int i){
Node n = new Node();
n.data = i;
tail = tail.link =n;
}
void reverse(){
tail = head;
head = reverse(head);
tail.link = null;//former head still links back, so clear it
}
private static Node reverse(Node head){
for (Node n=head.link, link; n!=null; n=link){//essentially replace head w/ the next and relink
link = n.link;
n.link = head;
head = n;
}
return head;
}
void print(){
for (Node n=head; n!=null;n=n.link){
System.out.println(n.data);
}
}
public static void main(String[] args) {
SList l = new SList();
l.add(1);l.add(2);l.add(3);l.add(4);
l.print();
System.out.println("==");
l.reverse();
l.print();
}
}
I was wondering something like that(I didnt test it, so):
invert(){
m(firstNode, null);
}
m(Node v, Node bef){
if(v.link != null)
m(v.link,v);
else
v.link=bef;
}
Without much testing,
Node head = this;
Node middle = null;
Node trail = null;
while (head != null) {
trail = middle;
middle = head;
head = head.link;
middle.link = trail;
}
head = middle;
return head;
public ListNode Reverse(ListNode list)
{
if (list == null) return null;
if (list.next == null) return list;
ListNode secondElem = list.next;
ListNode reverseRest = Reverse(secondElem);
secondElem.Next = list;
return reverseRest;
}
Hope this helps.