LinkedList recursion problem using Javascript - javascript

Looking for help solving this recursion problem: Given a linked list of indeterminate length, composed of nodes that store a reference to the next node....how can you return the list in reverse?
For example, node A --> B --> C --> D should return D-->C-->B-->A. The function is given any node and should return that list in reverse.
A node would consist of a couple values; an integer (i) and a next property which is the pointer to the next node.
const traverseList = (node) => {
if(node.next !== null) traverseList(node);
else return;
}
I'm trying this code but it's not working. Just looking for the missing pieces, please. Thanks for any help.

you are on the right path, just print it when you are returning from each node.
const traverseList = (node) => {
if (!node) return;
traverseList(node.next);
console.log(node.value); // or whatever you want to output
}

1) Store a reference to current(initially head), next(initially null), previous(initially null) node
2) Set tail to head, if your using a tail pointer
3) Traverse this list setting next to current.next, current.next to previous, previous to current, and finally current to next
4) Depending on how you do it after the loop, you must set current.next to previous and head to current
I have included both iterative and recursive solutions below.
class Node {
constructor(value, next){
this.value = value;
this.next = next;
}
}
class LinkedList {
constructor(){
this.size = 0;
this.head = null;
this.tail = null;
}
add(value){
const node = new Node(value, null);
if(this.head === null){
this.head = node;
this.tail = node;
} else {
this.tail.next = node;
this.tail = node;
}
this.size++;
}
traverse(){
let current = this.head;
while(current != null){
console.log(current.value);
current = current.next;
}
}
reverse(){
let current = this.head;
let previous = null;
let next = null;
this.tail = current;
while(current != null && current.next != null){
next = current.next;
current.next = previous;
previous = current;
current = next;
}
current.next = previous;
this.head = current;
}
_reverseRecursively(node){
if(node == null){
return null;
}
if(node.next == null){
this.head = node;
return node;
}
let nextNode = this._reverseRecursively(node.next);
nextNode.next = node;
node.next = null;
return node;
}
reverseRecursively(){
this.tail = this.head;
this._reverseRecursively(this.head);
}
}
const list = new LinkedList();
list.add(10);
list.add(12);
list.add(14);
console.log("Original List");
list.traverse();
list.reverse();
console.log("Reversed List - using loop");
list.traverse();
list.reverseRecursively();
console.log("Reversed List - using recursion");
list.traverse();

Related

Reverse a linked list... what is wrong with my implementation?

I'm having trouble reversing a linked list based on my implementation below. Is there something wrong or missing that I'm doing here?
class Node {
constructor(val) {
this.val = val;
this.next = null;
}
}
class SinglyLinkedList {
constructor() {
this.head = null;
this.length = 0;
}
push(val) {
var newNode = new Node(val);
var current = this.head;
if (!this.head)
this.head = newNode;
else {
// iterate to the end of the
// list
while (current.next) {
current = current.next;
}
// add node
current.next = newNode;
}
this.length++;
return this;
}
// reverse the list
reverse() {
var prev = null;
var curr = this.head;
while (curr !== null) {
var temp = curr.next;
curr.next = prev;
prev = curr;
curr = temp;
}
return this;
}
print() {
var arr = []
var current = this.head;
while(current) {
arr.push(current.val);
current = current.next;
}
console.log(arr);
}
}
Here's my implementation when I create the object and push some nodes
var list = new SinglyLinkedList();
list.push(1);
list.push(2);
list.push(3);
list.push(4);
Every time I ran list.reverse() then list.print() it only prints [1] only and not [4,3,2,1].
You correctly reverse the links between the nodes, but you never change what this.head is pointing at, so it is now pointing at the end of the list instead of the front of the list. So when you call print, print will start at the last node and then have nowhere to go.
reverse() {
var prev = null;
var curr = this.head;
while (curr !== null) {
var temp = curr.next;
curr.next = prev;
prev = curr;
curr = temp;
}
this.head = prev; // <--- added
return this;
}
You've not updated the head property in your reverse method. Just add this.head = prev; after the while loop and I believe it should work.

Linked List - find Nth element at index

I'm having an issue with my code for finding an element at a specific index for a Linked List.
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode != null) {
if (count === index) {
return currentNode;
count++;
currentNode = currentNode.next;
}
return -1;
}
}
When I do this, I'm getting the entire linked list instead of one specific node. So if I console.log(list.findElement(0)), I get the entire linked list. But if I console log console.log(list.findElement(1)), I get -1. But what I want there is the second node. Below is the rest of my code. Not entirely sure what's wrong with my findElement function.
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
//Length
this.length = 0;
}
//Push-front
pushFront(value) {
let node = new Node(value);
node.next = this.head;
this.head = node;
this.length++;
}
//Pop-front
popFront() {
if (this.head != null) {
this.head = this.head.next;
}
this.length--;
}
//Push-back
pushBack(value) {
let node = new Node(value);
if (this.head === null) {
this.head = node;
} else {
let currentNode = this.head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
this.length++;
}
There are a few issues with the logic in your findElement function. The primary issue is that count never changes from 0, so the function only works if the head is the sought element (e.g. index === 0) and returns -1 on any other input (this "fail" return should be moved outside of the while loop entirely).
Here's a version with count++ and currentNode = currentNode.next moved outside of the if into an implicit else:
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode) {
if (count === index) { // found the element
return currentNode;
}
count++; // increment counter
currentNode = currentNode.next; // move to next node
}
return -1;
}
Another issue is your popFront will decrease the length of the list to -1 if called on an empty list. The decrement should be conditional as well as the removal. This could cause harm in future implementations, but since you never use the list length, you can remove it entirely.
Putting it all together, here's a test program:
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedList {
constructor() {
this.head = null;
this.length = 0;
}
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode) {
if (count === index) {
return currentNode;
}
count++;
currentNode = currentNode.next;
}
return -1;
}
pushFront(value) {
const node = new Node(value);
node.next = this.head;
this.head = node;
this.length++;
}
popFront() {
if (this.head != null) {
this.head = this.head.next;
this.length--;
}
}
pushBack(value) {
const node = new Node(value);
if (this.head === null) {
this.head = node;
}
else {
let currentNode = this.head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = node;
}
this.length++;
}
}
const ll = new LinkedList();
ll.pushBack(1);
ll.pushBack(2);
ll.pushBack(3);
console.log(ll);
console.log(`First node: ${ll.findElement(0).value}`);
console.log(`Second node: ${ll.findElement(1).value}`);
console.log(`Third node: ${ll.findElement(2).value}`);
console.log(`Invalid index: ${ll.findElement(22).value}`);
You have a return statement as the first line of your if (count === index) conditional, which prevents further code from executing (meaning currentNode = currentNode.next will never get reached).
You're looking to move return currentNode down two lines, so that the subsequent node is referenced before the function returns.
findElement(index) {
let currentNode = this.head;
let count = 0;
while (currentNode != null) {
if (count === index) {
count++;
currentNode = currentNode.next;
return currentNode;
}
return -1;
}
}

How to implement methods add(value, index) and remove(index) for the SinglyLinkedList

I need to implement methods for removing and adding items by index. I was able to implement only at the beginning and end of the list. I understand that I have to break an array by index, add a new element to the end of the first list. and then add another part to it? Please help
class Node{
constructor(value, next, prev){
this.value = value;
this.next = next;
this.prev = prev;
}
}
class SinglyLinkedList{
constructor(){
this.head = null;
this.tail = null;
}
addFirst(value){
let node = new Node(value, this.head, null);
if (this.head){
this.head.prev = node;
}
else {
this.tail = node;
}
this.head = node;
}
removeFirst(){
if (!this.head){
return null;
}
let value = this.head.value;
this.head = this.head.next;
if (this.head) {
this.head.prev = null;
}
else {
this.tail = null;
}
return value;
}
toString(){
let str = "";
let current = this.head;
while (current){
str += current.value + " ";
current = current.next;
}
console.log(str.trim());
}
}
The add(value, index) will look like this -
add(value, index){
let node = new Node(value, null, null);
if(!this.head){
this.head = node;
} else if(index == 0) {
node.next = this.head;
this.head = node;
} else {
let current = this.head;
let d = 1;
while(current !== NULL){
if(d === index){
node.next = current.next;
current.next = node;
break;
}
current = current.next;
d++;
}
}
return head;
}
Notice here the algorithm:
Create a new node with given value.
if the this.head is currently NULL then set the new node to this.head
if the given index is 0 then also set the node to this.head
else loop over the linked list and find the right position and set the node there
The remove(index) method will look like this:
remove(index) {
if(!this.head){
return;
}
let temp = this.head;
if(index === 0){
this.head = temp.next;
return;
}
for(let i=0;temp!==null && i<index - 1;i++){
temp = temp.next;
if(temp === null || temp->next === null){
return;
}
let next = temp.next.next;
temp.next = next;
}
}
Notice here the algorithm for remove(index) is also very similar:
if the this.head is not defined yet then return
if the node to be removed is the head then assign new head and return
else loop over the linked list until the position is found then change the next properties to remove the node at the desired position
You can implement removeAtIndex() in the following way :
removeAtIndex(index){
if (!this.head){
return null;
}
var i = 1;
var temp = this.head;
var save;
console.log(temp);
while(i < index && temp){
save = temp;
temp = temp.next;
i++;
}
if(temp){
save.next = temp.next;
} else{
save.next = undefined;
}
return temp.value;
}
Basically just iterate to that index and maintain reference to the node before it and the reference to the node after the index of node which you want to delete. And simply save the reference of next node node which you want to delete in the next of the previous node of the node which you want to delete.
You an implement add in the similar way.
In the snippet removeAtIndex() functionality is demonstrated you can make addAtIndex in the same way.
class Node{
constructor(value, next, prev){
this.value = value;
this.next = next;
this.prev = prev;
}
}
class SinglyLinkedList{
constructor(){
this.head = null;
this.tail = null;
}
addFirst(value){
let node = new Node(value, this.head, null);
if (this.head){
this.head.prev = node;
}
else {
this.tail = node;
}
this.head = node;
}
removeFirst(){
if (!this.head){
return null;
}
let value = this.head.value;
this.head = this.head.next;
if (this.head) {
this.head.prev = null;
}
else {
this.tail = null;
}
return value;
}
removeAtIndex(index){
if (!this.head){
return null;
}
var i = 1;
var temp = this.head;
var save;
while(i < index && temp){
save = temp;
temp = temp.next;
i++;
}
if(temp){
save.next = temp.next;
} else{
save.next = undefined;
}
return temp.value;
}
toString(){
let str = "";
let current = this.head;
while (current){
str += current.value + " ";
current = current.next;
}
console.log(str.trim());
}
}
list = new SinglyLinkedList();
list.addFirst(1);
list.addFirst(2);
list.addFirst(3);
list.removeAtIndex(2);
console.log(list.toString());

Why does the method of inserting a node by index not work?

I want to insert a node by index using the add () method but it does not work help fix it.
This is how the call should look like:
list.add ('2', 1); // At the list: '1', '2', '3'
But when I make a call an error is triggered:
throw new Error("Position Node Doesnt Exist!")
All my code:
class Node {
constructor(value) {
this.value = value; // value in the node
this.next = null; // link to the next node
}
}
class SinglyLinkedList {
constructor() {
/*pointer to the knot-head
(first element) of the list*/
this.head = null;
/*pointer to the node-tail
(last item) of the list*/
this.tail = null;
this.length = 0;
}
//insert to the beginning (returns the inserted value)
addFirst(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.head) {
newNode.next = this.head;
//this.head = newNode;
} else {//Linked list is empty
this.tail = newNode;
//this.head = newNode
}
//set the head to the new node
this.head = newNode;
//increment count
this.length++;
}
//insert to the end(returns the inserted value)
addLast(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.tail) {
this.tail.next = newNode;
//this.tail = newNode;
} else {
this.head = newNode;
//this.tail = newNode
}
this.tail = newNode;
//increment count
this.length++;
}
findIndex(item) {
let currentNode = this.head;
while (currentNode) {
if (currentNode.value === item) {
return currentNode;
}
currentNode = currentNode.next;
}
return null;
}
add(value, index) {
//create the new node based on the name passed
let newNode = new Node(value);
//find the position or item node we want to insert after.
let positionNode = this.findIndex(index);
if (positionNode != null) {
//first set the next pointer of new node to be that of position nodes next
newNode.next = positionNode.next;
//finally update the positionNode's next to be the new node
positionNode.next = newNode;
this.length++;
} else {
//position not found, return error
throw new Error("Position Node Doesnt Exist!")
}
}
}
let list = new SinglyLinkedList();
list.addFirst('1');
list.addLast('3');
list.add('2', 1);
console.log(list);
You are trying to compare strings with numbers in the findIndex method at:
if (currentNode.value === item) {
To allow auto type coercion, you can use the double equal operator. Or you could convert both values to the same type(number or string)
if (currentNode.value == item) {
Please find the edited working snippet below.
class Node {
constructor(value) {
this.value = value; // value in the node
this.next = null; // link to the next node
}
}
class SinglyLinkedList {
constructor() {
/*pointer to the knot-head
(first element) of the list*/
this.head = null;
/*pointer to the node-tail
(last item) of the list*/
this.tail = null;
this.length = 0;
}
//insert to the beginning (returns the inserted value)
addFirst(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.head) {
newNode.next = this.head;
//this.head = newNode;
} else {//Linked list is empty
this.tail = newNode;
//this.head = newNode
}
//set the head to the new node
this.head = newNode;
//increment count
this.length++;
}
//insert to the end(returns the inserted value)
addLast(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.tail) {
this.tail.next = newNode;
//this.tail = newNode;
} else {
this.head = newNode;
//this.tail = newNode
}
this.tail = newNode;
//increment count
this.length++;
}
findIndex(item) {
let currentNode = this.head;
while (currentNode) {
if (currentNode.value == item) {
return currentNode;
}
currentNode = currentNode.next;
}
return null;
}
add(value, index) {
//create the new node based on the name passed
let newNode = new Node(value);
//find the position or item node we want to insert after.
debugger;
let positionNode = this.findIndex(index);
if (positionNode != null) {
//first set the next pointer of new node to be that of position nodes next
newNode.next = positionNode.next;
//finally update the positionNode's next to be the new node
positionNode.next = newNode;
this.length++;
} else {
//position not found, return error
throw new Error("Position Node Doesnt Exist!")
}
}
}
let list = new SinglyLinkedList();
list.addFirst('1');
list.addLast('3');
list.add('2', 1);
console.log(list);
You could track which index you're on within findIndex instead of comparing values.
class Node {
constructor(value) {
this.value = value; // value in the node
this.next = null; // link to the next node
}
}
class SinglyLinkedList {
constructor() {
/*pointer to the knot-head
(first element) of the list*/
this.head = null;
/*pointer to the node-tail
(last item) of the list*/
this.tail = null;
this.length = 0;
}
//insert to the beginning (returns the inserted value)
addFirst(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.head) {
newNode.next = this.head;
//this.head = newNode;
} else {//Linked list is empty
this.tail = newNode;
//this.head = newNode
}
//set the head to the new node
this.head = newNode;
//increment count
this.length++;
}
//insert to the end(returns the inserted value)
addLast(value) {
//create a new Node
let newNode = new Node(value);
//Handle case for when linked list is not empty
if (this.tail) {
this.tail.next = newNode;
//this.tail = newNode;
} else {
this.head = newNode;
//this.tail = newNode
}
this.tail = newNode;
//increment count
this.length++;
}
findIndex(item) {
let currentNode = this.head;
let index = 0;
while (currentNode) {
if (index === item - 1) {
return currentNode;
}
index++;
currentNode = currentNode.next;
}
return null;
}
add(value, index) {
//create the new node based on the name passed
let newNode = new Node(value);
//find the position or item node we want to insert after.
let positionNode = this.findIndex(index);
if (positionNode != null) {
//first set the next pointer of new node to be that of position nodes next
newNode.next = positionNode.next;
//finally update the positionNode's next to be the new node
positionNode.next = newNode;
this.length++;
} else {
//position not found, return error
throw new Error("Position Node Doesnt Exist!")
}
}
}
let list = new SinglyLinkedList();
list.addFirst('1');
list.addLast('3');
list.add('2', 1);
console.log(list);
Your logics seems wrong.
The findindex function finds the item with the some value.
You call it with an index as a parameter... That is wrong.
You need a findItem method with index as parameter
if(index<0||index>length) {return null or head or tail...}
let currentNode = this.head;
let currentIndex=0;
while (currentIndex<index) {
currentNode = currentNode.next;
CurrentIndex++;
}
return currentNode;

Reverse Linked List using Iteration in Javascript

I am getting the desired output i.e the reversed linkedlist on the 3rd iteration in the console.log below.
But I have return previous and it still returns the value from the 1st Iteration.
Even console.log(previous) instead of return previous, gives the desired output.
But now the question is how to display it in the end?
Can someone please explain, what's wrong?
reverse(){
var current= this.head,previous=null;
while(current)
{
var next = current.next;
current.next = previous;
previous = current;
current = next;
console.log(previous); //I am getting my answer at the third iteration
}
return previous; //
}
class LinkedList {
constructor() {
this.head = null;
this.length = 0;
}
add(value) {
var node = new Node(value);
if (this.head == null) {
this.head = node;
this.length++;
} else {
var current = this.head;
while (current.next) {
current = current.next;
}
current.next = node;
this.length++;
}
}
reverse() {
var current = this.head,
previous = null;
while (current) {
var next = current.next;
current.next = previous;
previous = current;
current = next;
console.log(previous);
}
return previous;
}
}
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
var ll = new LinkedList();
ll.add(3);
ll.add(2);
ll.add(7);
ll.reverse();
console.log(ll.head);
It was giving the desired output on return previous
All that was needed was to call the function ll.reverse() or console.log(ll.reverse()) for this specific question.
class LinkedList {
constructor() {
this.head = null;
this.length = 0;
}
add(value) {
var node = new Node(value);
if (this.head == null) {
this.head = node;
this.length++;
} else {
var current = this.head;
while (current.next) {
current = current.next;
}
current.next = node;
this.length++;
}
}
reverse() {
var current = this.head,
previous = null;
while (current) {
var next = current.next;
current.next = previous;
previous = current;
current = next;
}
return previous;
}
}
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
var ll = new LinkedList();
ll.add(3);
ll.add(2);
ll.add(7);
ll.add(9);
console.log(ll.reverse());

Categories

Resources