i just found this difficult interview question online and I was hoping someone could help me make sense of it. It is a generic question...given a singly linked list, swap each element of the list in pairs so that 1->2->3->4 would become 2->1->4->3.
You have to swap the elements, not the values. The answer should work for circular lists where the tail is pointing back to the head of the list. You do not have to check if the tail points to an intermediate (non-head) element.
So, I thought:
public class Node
{
public int n; // value
public Node next; // pointer to next node
}
What is the best way to implement this? Can anyone help?
I agree with #Stephen about not giving the answer (entirely), but I think I should give you hints.
An important thing to understand is that Java does not explicitly specify pointers - rather, whenever a non-primitive (e.g. not char, byte, int, double, float, long, boolean, short) is passed to a function, it is passed as a reference. So, you can use temporary variables to swap the values. Try to code one yourself or look below:
public static void swapNodeNexts(final Node n1, final Node n2) {
final Node n1Next = n1.next;
final Node n2Next = n2.next;
n2.next = n1Next;
n1.next = n2Next;
}
Then you'll need a data structure to hold the Nodes. It's important that there be an even number of Nodes only (odd numbers unnecessarily complicate things). It's also necessary to initialize the nodes. You should put this in your main method.
public static final int NUMPAIRS = 3;
public static void main(final String[] args) {
final Node[] nodeList = new Node[NUMPAIRS * 2];
for (int i = 0; i < nodeList.length; i++) {
nodeList[i] = new Node();
nodeList[i].n = (i + 1) * 10;
// 10 20 30 40
}
// ...
}
The important part is to set the Node next values. You can't just loop through with a for loop for all of them, because then the last one's next would throw an IndexOutOfBoundsException. Try to make one yourself, or peek at mine.
for (int i = 0; i < nodeList.length - 1; i++) {
nodeList[i].next = nodeList[i + 1];
}
nodeList[nodeList.length - 1].next = nodeList[0];
Then run your swap function on them with a for loop. But remember, you don't want to run it on every nodeā¦ think about it a bit.
If you can't figure it out, here is my final code:
// Node
class Node {
public int n; // value
public Node next; // pointer to next node
#Override
public String toString() {
return "Node [n=" + n + ", nextValue=" + next.n + "]";
}
}
// NodeMain
public class NodeMain {
public static final int NUMPAIRS = 3;
public static void main(final String[] args) {
final Node[] nodeList = new Node[NUMPAIRS * 2];
for (int i = 0; i < nodeList.length; i++) {
nodeList[i] = new Node();
nodeList[i].n = (i + 1) * 10;
// 10 20 30 40
}
for (int i = 0; i < nodeList.length - 1; i++) {
nodeList[i].next = nodeList[i + 1];
}
nodeList[nodeList.length - 1].next = nodeList[0];
// This makes 1 -> 2 -> 3 -> 4 -> 1 etc.
printNodes(nodeList);
for (int i = 0; i < nodeList.length; i += 2) {
swapNodeNexts(nodeList[i], nodeList[i + 1]);
}
// Now: 2 -> 1 -> 4 -> 3 -> 1 etc.
printNodes(nodeList);
}
private static void printNodes(final Node[] nodeList) {
for (int i = 0; i < nodeList.length; i++) {
System.out.println("Node " + (i + 1) + ": " + nodeList[i].n
+ "; next: " + nodeList[i].next.n);
}
System.out.println();
}
private static void swapNodeNexts(final Node n1, final Node n2) {
final Node n1Next = n1.next;
final Node n2Next = n2.next;
n2.next = n1Next;
n1.next = n2Next;
}
}
I hope you were able to figure out at least some of this with guidance. More importantly, however, it's important that you understand the concepts here. If you have any questions, just leave a comment.
Simple recursive solution in Java:
public static void main(String[] args)
{
Node n = new Node(1);
n.next = new Node(2);
n.next.next = new Node(3);
n.next.next.next = new Node(4);
n.next.next.next.next = new Node(5);
n = swap(n);
}
public static Node swap(Node n)
{
if(n == null || n.next == null)
return n;
Node buffer = n;
n = n.next;
buffer.next = n.next;
n.next = buffer;
n.next.next = swap(buffer.next);
return n;
}
public static class Node
{
public int data; // value
public Node next; // pointer to next node
public Node(int value)
{
data = value;
}
}
Methods needed to run this program :
public static void main(String[] args) {
int iNoNodes = 10;
System.out.println("Total number of nodes : " + iNoNodes);
Node headNode = NodeUtils.createLinkedListOfNElements(iNoNodes);
Node ptrToSecondNode = headNode.getNext();
NodeUtils.printLinkedList(headNode);
reversePairInLinkedList(headNode);
NodeUtils.printLinkedList(ptrToSecondNode);
}
Approach is almost same, others are trying to explain. Code is self-explainatory.
private static void reversePairInLinkedList(Node headNode) {
Node tempNode = headNode;
if (tempNode == null || tempNode.getNext() == null)
return;
Node a = tempNode;
Node b = tempNode.getNext();
Node bNext = b.getNext(); //3
b.setNext(a);
if (bNext != null && bNext.getNext() != null)
a.setNext(bNext.getNext());
else
a.setNext(null);
reversePairInLinkedList(bNext);
}
Algo(node n1) -
keep 2 pointers n1 and n2, at the current 2 nodes. n1 --> n2 --->...
if(n1 and n2 link to each other) return n2;
if(n1 is NULL) return NULL;
if(n2 is NULL) return n1;
if(n1 and n2 do not link to each other and are not null)
change the pointer of n2 to n1.
call the algorthm recursively on n2.next
return n2;
Code (working) in c++
#include <iostream>
using namespace std;
class node
{
public:
int value;
node* next;
node(int val);
};
node::node(int val)
{
value = val;
}
node* reverse(node* n)
{
if(n==NULL) return NULL;
node* nxt = (*n).next;
if(nxt==NULL) return n;
if((*nxt).next==n) return nxt;
else
{
node* temp = (*nxt).next;
(*nxt).next = n;
(*n).next = reverse(temp);
}
return nxt;
}
void print(node* n)
{
node* temp = n;
while(temp!=NULL)
{
cout<<(*temp).value;
temp = (*temp).next;
}
cout << endl;
}
int main()
{
node* n = new node(0);
node* temp = n;
for(int i=1;i<10;i++)
{
node* n1 = new node(i);
(*temp).next = n1;
temp = n1;
}
print(n);
node* x = reverse(n);
print(x);
}
The general approach to take is to step through the list, and on every other step you reorder the list nodes by assigning the node values.
But I think you will get more out of this (i.e. learn more) if you actually design, implement and test this yourself. (You don't get a free "phone a friend" or "ask SO" at a job interview ...)
Yep, write an iterative routine that progresses two links in each iteration. Remember the link from the previous iteration so that you can back-patch it, then swap the current two links. The tricky parts are getting started (to a small extent) and knowing when to finish (to a larger one), especially if you end up having an odd number of elements.
public static Node swapInPairs(Node n)
{
Node two;
if(n ==null ||n.next.next ==null)
{
Node one =n;
Node twoo = n.next;
twoo.next = one;
one.next =null;
return twoo;
}
else{
Node one = n;
two = n.next;
Node three = two.next;
two.next =one;
Node res = swapInPairs(three);
one.next =res;
}
return two;
}
I wrote the code at atomic level. So i hope it is self explanatory. I tested it. :)
public static Node swapPairs(Node start)
{
// empty or one-node lists don't need swapping
if (start == null || start.next == start) return start;
// any list we return from here on will start at what's the second node atm
Node result = start.next;
Node current = start;
Node previous = null; // so we can fix links from the previous pair
do
{
Node node1 = current;
Node node2 = current.next;
// swap node1 and node2 (1->2->? ==> 2->1->?)
node1.next = node2.next;
node2.next = node1;
// If prev exists, it currently points at node1, not node2. Fix that
if (previous != null) previous.next = node2;
previous = current;
// only have to bump once more to get to the next pair;
// swapping already bumped us forward once
current = current.next;
} while (current != start && current.next != start);
// The tail needs to point at the new head
// (if current == start, then previous is the tail, otherwise current is)
((current == start) ? previous : current).next = result;
return result;
}
//2.1 , 2.2 Crack the code interview
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
struct Node{
int info;
struct Node *next;
};
struct Node *insert(struct Node *head,int data){
struct Node *temp,*ptr;
temp = (struct Node*)malloc(sizeof(struct Node));
temp->info=data;
temp->next=NULL;
if(head==NULL)
head=temp;
else{
ptr=head;
while(ptr->next!=NULL)
{
ptr=ptr->next;
}
ptr->next=temp;
}
return head;
}
struct Node* reverse(struct Node* head){
struct Node *current,*prev,*next;
current = head;
prev=NULL;
while(current!=NULL){
next=current->next;
current->next = prev;
prev=current;
current=next;
}
head=prev;
return head;
}
/*nth till last element in linked list*/
void nthlastElement(struct Node *head,int n){
struct Node *ptr;
int last=0,i;
ptr=head;
while(ptr!=NULL){
last++;
//printf("%d\n",last);
ptr=ptr->next;
}
ptr=head;
for(i=0;i<n-1;i++){
ptr=ptr->next;
}
for(i=0;i<=(last-n);i++){
printf("%d\n",ptr->info);
ptr=ptr->next;
}
}
void display(struct Node* head){
while(head!=NULL){
printf("Data:%d\n",head->info);
head=head->next;
}
}
void deleteDup(struct Node* head){
struct Node *ptr1,*ptr2,*temp;
ptr1=head;
while(ptr1!=NULL&&ptr1->next!=NULL){
ptr2=ptr1;
while(ptr2->next!=NULL){
if(ptr1->info==ptr2->next->info){
temp=ptr2->next;
ptr2->next=ptr2->next->next;
free(temp);
}
else{
ptr2=ptr2->next;
}
}
ptr1=ptr1->next;
}
}
void main(){
struct Node *head=NULL;
head=insert(head,10);
head=insert(head,20);
head=insert(head,30);
head=insert(head,10);
head=insert(head,10);
printf("BEFORE REVERSE\n");
display(head);
head=reverse(head);
printf("AFTER REVERSE\n");
display(head);
printf("NTH TO LAST\n");
nthlastElement(head,2);
//printf("AFTER DUPLICATE REMOVE\n");
//deleteDup(head);
//removeDuplicates(head);
//display(head);
}
public class Node
{
public int n; // value
public Node next; // pointer to next node
}
Node[] n = new Node[length];
for (int i=0; i<n.length; i++)
{
Node tmp = n[i];
n[i] = n[i+1];
n[i+1] = tmp;
n[i+1].next = n[i].next;
n[i].next = tmp;
}
Related
import java.io.*;
import java.util.Arrays;
public class tester {
static public class LinkedList {
Node head; // head of list
Node sorted;
int size;
// Linked list Node.
// This inner class is made static
// so that main() can access it
public class Node {
Object data;
Node next;
Node() {
}
// constructor
Node(Object data) {
this.data = data;
next = null;
}
// constructor
Node(Object data, Node n) {
this.data = data;
next = n;
}
}
public void addFirst(Object d) {
head = new Node(d);
size++;
}
public void addLast(Object d) {
Node temp = head;
while (temp != null) {
temp = temp.next;
}
temp = new Node(d,null);
size++;
}
int getSize() {
return size;
}
boolean isSorted()
{
if (head == null)
return true;
// Traverse the list till last node and return
// false if a node is smaller than or equal
// its next.
for (Node t = head; t.next != null; t=t.next)
if ((int)t.data <= (int)t.next.data)
return false;
return true;
}
void InsertionSort()
{
// Initialize sorted linked list
sorted = null;
Node current = head;
// Traverse the given linked list and insert every
// node to sorted
while (current != null)
{
// Store next for next iteration
Node next = current.next;
// insert current in sorted linked list
sortedInsert(current);
// Update current
current = next;
}
// Update head_ref to point to sorted linked list
head = sorted;
}
void sortedInsert(Node newnode)
{
/* Special case for the head end */
if (sorted == null || (int)sorted.data >= (int)newnode.data)
{
newnode.next = sorted;
sorted = newnode;
}
else
{
Node current = sorted;
/* Locate the node before the point of insertion */
while (current.next != null && (int)current.next.data < (int)newnode.data)
{
current = current.next;
}
newnode.next = current.next;
current.next = newnode;
}
}
public void MergeSort() {
Queue q = new Queue();
int count = 0;
int[] sublist1 = null;
int[] sublist2 = null;
int[] tempList = null;
// Node cur = head;
for (Node cur = head; cur != null; cur = cur.next) {
LinkedList newList = new LinkedList();
newList.addFirst(cur.data);
q.enqueue(newList);
}
while (q.size > 1) {
sublist1[count] = (int) q.dequeue();
if (q.size >= 1) {
sublist2[count] = (int) q.dequeue();
}
Arrays.sort(sublist1);
Arrays.sort(sublist2);
tempList = merge(sublist1, sublist2);
}
q.enqueue(tempList);
}
public int[] merge(int[] a, int[] b) {
int[] answer = new int[a.length + b.length];
int i = 0, j = 0, k = 0;
while (i < a.length && j < b.length)
answer[k++] = a[i] < b[j] ? a[i++] : b[j++];
while (i < a.length)
answer[k++] = a[i++];
while (j < b.length)
answer[k++] = b[j++];
return answer;
}
}
static class Queue {
int front, rear, size;
int capacity;
Object array[];
// constructor
public Queue() {
front = 0;
rear = 0;
size = 0;
}
// constructor
public Queue(int capacity) {
this.capacity = capacity;
front = this.size = 0;
rear = capacity - 1;
array = new Object[this.capacity];
}
boolean isFull(Queue queue) {
return (queue.size == queue.capacity);
}
boolean isEmpty(Queue queue) {
return (queue.size == 0);
}
void enqueue(Object newList) {
if (isFull(this))
return;
this.rear = (this.rear + 1) % this.capacity;
this.array[this.rear] = newList;
this.size = this.size + 1;
}
Object dequeue() {
if (isEmpty(this))
return Integer.MIN_VALUE;
Object item = (int) this.array[this.front];
this.front = (this.front + 1) % this.capacity;
this.size = this.size - 1;
return item;
}
}
public static void main(String[] args) {
LinkedList A = new LinkedList();
LinkedList A2 = new LinkedList();
int ramdomListSize = 20000;
for(int i = 0; i < ramdomListSize; i++) {
int randomInt = (int)(Math.random() * 3000000);
A.addLast(randomInt);
A2.addLast(randomInt);
}
//measure the time cost of merge sort
double then = System.currentTimeMillis();
A.MergeSort();
double now = System.currentTimeMillis();
System.out.println("Time cost in milliseconds for mergesort " + (now - then));
System.out.println(A.isSorted()); //verify that your merge sort implementation works.
System.out.println("Size of list A is: " + A.getSize());
//measure the time cost of insertion sort
then = System.currentTimeMillis();
A2.InsertionSort();
now = System.currentTimeMillis();
System.out.println("Time cost in milliseconds for insertionsort " + (now - then));
System.out.println(A2.isSorted() ); //verify that your insertion sort works.
System.out.println("Size of list A2 is: " + A2.getSize());
}//end of main
}
Expected output:
Time cost in milliseconds for mergesort: 37.0
true
Size of list A is: 20000
Time cost in milliseconds for insertionsort: 660.0
true
Size of list A2 is: 20000
My Output:
Time cost in milliseconds for mergesort: 1.0
true
Size of list A is: 20000
Time cost in milliseconds for insertionsort: 0.0
true
Size of list A2 is: 20000
Your InsertionSort() doesn't do anything.
Node current = head;
while (current != null) {
....
}
You never assign head field, so it is always null and the loop is never executed.
The only assignment to head is done in addFirst() method which is never called.
You should declare a field Node current to keep track of the last Node object.
Your method addLast(Object d) does not add the object to the list. Storing a different object in a variable does not affect the previously stored object so temp = new Node(d,null); will only change value of the variable temp.
The method should be like this
public void addLast(Object d) {
if (current != null) {
current.next = new Node(d,null);
current = current.next;
}
else {
head = new Node(d, null);
current = head;
}
size++;
}
Your implementation of merge sort is also incorrect. addFirst should store previous head before updating and make the next field of the new head point to the old one. sublist1 and sublist2 are always null and count always remains 0. If you want to sort using merge sort, Arrays.sort should not be used because it uses quick sort for primitive types like int. Check out the correct implementation of merge sort here.
I'm trying a standard interview question, which is to add two digits in the form of linkedlists and return the added answer. Here is the question:
You are given two linked lists representing two non-negative numbers.
The digits are stored in reverse order and each of their nodes contain
a single digit. Add the two numbers and return it as a linked list.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8
342 + 465 = 807 Make sure there are no trailing zeros in the output list So, 7 -> 0 -> 8 -> 0 is not a valid response even though
the value is still 807.
Now, the code I am writing takes in two arguments in the form of ListNode datatypes which is the starting node of the LinkedLists. What I am not understanding is
How do I maintain the head node of the list to reference later?
How does call by value and call by reference work in Java? I've dealt with pointers and call by reference in C++ but I've been trying stuff in Java now and it's pretty different.
class ListNode {
public int val;
public ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class Solution {
public ListNode reverse(ListNode head) {
ListNode curr = head;
ListNode next = null;
ListNode prev = null;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
public ListNode addTwoNumbers(ListNode a, ListNode b) {
ListNode node = null;
ListNode head = null;
boolean carry = false;
while (a != null || b != null) {
int f = 0, s = 0;
if (carry) {
f++;
}
carry = false;
if (a != null) {
f += a.val;
a = a.next;
}
if (b != null) {
s = b.val;
b = b.next;
}
if (f + s > 9) {
carry = true;
}
int curr = (f + s) % 10;
node = new ListNode(curr);
if (head == null) {
head = node;
}
node = node.next; //warning that 'value of node assigned is never used'
}
if (carry) {
node = new ListNode(1);
}
printList(head);
return node;
}
}
node plays an ambiguous role.
node = new ListNode(curr);
node = node.next; // assigns null
Rename node into previous and do:
int curr = (f + s) % 10;
ListNode newNode = new ListNode(curr);
if (head == null) { // Or `previous == null`
head = newNode;
} else {
previous.next = newNode;
}
previous = newNode;
...
return head;
The technique to handle head is to make it a private field of a container class LinkedList.
As in java the parameter passing is call-by-value: f(a) never changes the variable a: the slot where the object pointer / value is stored. Instead to object pointer / value is pushed on the stack. (The object value may have its fields changed.)
So a recursive insert might look like head = insert(head, ...).
In C on can use aliasing, not only for parameter passing:
ListNode* head = NULL;
ListNode** node = &head;
shile (...) {
...
*node = newNode;
node = &(newNode->next);
}
Why so complicated?
public class Solution {
public ListNode addTwoNumbers(ListNode a, ListNode b) {
int firstNumber = nodeToNumber(a);
int secondNumber = nodeToNumber(b);
return numberToNode(firstNumber + secondNumber);
}
public int nodeToNumber(ListNode node) {
if (node.next != null) return node.value + 10 * nodeToNumber(node.next);
return node.value;
}
public ListNode numberToNode(int number) {
ListNode result = new ListNode(number % 10);
if (number > 10) result.next = numberToNode(number / 10);
return result;
}
}
This is my first question here.
I am trying to manually sort a linked list of integers in java and I can not figure out what is wrong with my code. Any suggestions? I don't get any error, however I still have my output unordered. I tried a few different ways, but nothing worked. I appreciate if anyone can help me with that.
public class Node {
int data;
Node nextNode;
public Node(int data) {
this.data = data;
this.nextNode = null;
}
public int getData() {
return this.data;
}
} // Node class
public class DataLinkedList implements DataInterface {
private Node head;
private int size;
public DataLinkedList(){
this.head = null;
this.size = 0;
}
public void add(int data) {
Node node = new Node(data);
if (head == null) {
head = node;
} else {
Node currentNode = head;
while(currentNode.nextNode != null) {
currentNode = currentNode.nextNode;
}
currentNode.nextNode = node;
}
size++;
}
public void sort() {
if (size > 1) {
for (int i = 0; i < size; i++ ) {
Node currentNode = head;
Node next = head.nextNode;
for (int j = 0; j < size - 1; j++) {
if (currentNode.data > next.data) {
Node temp = currentNode;
currentNode = next;
next = temp;
}
currentNode = next;
next = next.nextNode;
}
}
}
}
public int listSize() {
return size;
}
public void printData() {
Node currentNode = head;
while(currentNode != null) {
int data = currentNode.getData();
System.out.println(data);
currentNode = currentNode.nextNode;
}
}
public boolean isEmpty() {
return size == 0;
}
} // DataInterface class
public class DataApp {
public static void main (String[]args) {
DataLinkedList dll = new DataLinkedList();
dll.add(8);
dll.add(7);
dll.add(6);
dll.add(4);
dll.add(3);
dll.add(1);
dll.sort();
dll.printData();
System.out.println(dll.listSize());
}
} // DataApp class
The problem, as expected, comes in method sort():
public void sort() {
if (size > 1) {
for (int i = 0; i < size; i++ ) {
Node currentNode = head;
Node next = head.nextNode;
for (int j = 0; j < size - 1; j++) {
if (currentNode.data > next.data) {
Node temp = currentNode;
currentNode = next;
next = temp;
}
currentNode = next;
next = next.nextNode;
}
}
}
}
A minor problem is just do always execute the bubble sort n*n times. It is actually better check whether there was a change between any pair in the list. If it was, then there is the need to run again all over the list; if not, there isn't. Think of the marginal case in which a list of 100 elements is already sorted when sort() is called. This means that nodes in the list would be run over for 10000 times, even when there is actually nothing to do!
The main problem, though, is that you are exchanging pointers to the nodes in your list.
if (currentNode.data > next.data) {
Node temp = currentNode;
currentNode = next;
next = temp;
}
If you translate currentNode by v[i] and next by v[i - 1], as if you were sorting an array, that would do. However, you are just changing pointers that you use to run over the list, without effect in the list itself. The best solution (well, provided you are going to use BubbleSort, which is always the worst solution) would be to exchange the data inside the nodes.
if (currentNode.data > next.data) {
int temp = currentNode.data;
currentNode.data = next.data;
next.data = temp;
}
However, for a matter of illustration of the concept, I'm going to propose changing the links among nodes. These pointers are the ones which actually mark the sorting in the list. I'm talking about the nextNode attribute in the Node class.
Enough chat, here it is:
public void sort() {
if (size > 1) {
boolean wasChanged;
do {
Node current = head;
Node previous = null;
Node next = head.nextNode;
wasChanged = false;
while ( next != null ) {
if (current.data > next.data) {
/*
// This is just a literal translation
// of bubble sort in an array
Node temp = currentNode;
currentNode = next;
next = temp;*/
wasChanged = true;
if ( previous != null ) {
Node sig = next.nextNode;
previous.nextNode = next;
next.nextNode = current;
current.nextNode = sig;
} else {
Node sig = next.nextNode;
head = next;
next.nextNode = current;
current.nextNode = sig;
}
previous = next;
next = current.nextNode;
} else {
previous = current;
current = next;
next = next.nextNode;
}
}
} while( wasChanged );
}
}
The explanation for a "double" code managing the node exchange is that, since you have to change the links among nodes, and this is just a single linked list, then you have to keep track of the previous node (you don't have a header node, either), which the first time is head.
if ( previous != null ) {
Node sig = next.nextNode;
previous.nextNode = next;
next.nextNode = current;
current.nextNode = sig;
} else {
Node sig = next.nextNode;
head = next;
next.nextNode = current;
current.nextNode = sig;
}
You can find the code in IdeOne, here: http://ideone.com/HW5zw7
Hope this helps.
You need to swap the data not just the nodes.
public void sort() {
if (size > 1) {
for (int i = 0; i < size; i++ ) {
Node currentNode = head;
Node next = head.nextNode;
for (int j = 0; j < size - 1; j++) {
if (currentNode.data > next.data) {
int temp = currentNode.data;
currentNode.data = next.data;
next.data = temp;
}
currentNode = next;
next = next.nextNode;
}
}
}
}
you can write this methode like this:
class Node {
int data = 0;
Node next;
public Node(int data) {
this.data = data;
}
}
public void sort() {
Node current = head;
while (current != null) {
Node second = current.next;
while (second != null) {
if (current.data > second.data) {
int tmp = current.data;
current.data = second.data;
second.data = tmp;
}
second = second.next;
}
current = current.next;
}
}
Here is my singly linked list code:
public class SinglyLinkedList {
private static Node head;
private static int listSize;
private static class Node {
int value;
Node next;
Node(int i) {
value = i;
next = null;
}
}
public static void main(String[] args) {
head = null;
listSize = 0;
for (int i = 0; i < 10; i++) {
Node n = new Node(i);
if (head == null) {
head = n;
} else {
getLastNode(head).next = n;
}
listSize++;
}
printNodeValues(head);
Node revHead = reverseList(head);
printNodeValues(revHead);
}
private static Node reverseList(Node head) {
Node reverseHead = getLastNode(head);
Node reference = reverseHead;
while (listSize>0){
Node temp = getPreviousNode(reference, head);
Node last = getLastNode(reverseHead);
temp.next = null;
last.next = temp;
reference = temp;
listSize--;
}
return reverseHead;
}
private static Node getPreviousNode(Node reference, Node head) {
Node temp = head;
while (temp != null) {
if (temp.next == reference) {
break;
} else {
temp = temp.next;
}
}
return temp;
}
private static Node getLastNode(Node n) {
Node temp = n;
while (temp != null) {
if (temp.next == null) {
break;
} else {
temp = temp.next;
}
}
return temp;
}
public static void printNodeValues(Node h) {
while (h != null) {
System.out.print(h.value + " ");
h = h.next;
}
System.out.println();
}
}
The problem is with my reverseList(Node) method. When I run the program, I get the following error:
Exception in thread "main" java.lang.NullPointerException
at SinglyLinkedList.reverseList(SinglyLinkedList.java:44) -> temp = null;
at SinglyLinkedList.main(SinglyLinkedList.java:33) -> Node revHead = reverseList(head);
My printNodeValues works fine, and prints
0 1 2 3 4 5 6 7 8 9
and I'm trying to use reverseList to print
9 8 7 6 5 4 3 2 1 0.
There are many very bad things in your code. Worst of all : why is everything static ? What's the point of writing a list class that can be instantiated only once ?
Then, the size of the list should never be affected by a reverse operation, and you don't even need a counter since you just have to iterate over the list until you find a node which has no successor.
private static Node reverseList(Node head) {
Node res = null;
while (head != null) {
Node node = new Node(head.value);
node.next = res;
res = node;
head = head.next;
}
return res;
}
Your reverseList() method needs to skip the iteration when it has reached the first node in the original list because it's previous node doesn't exist. This first node has already be assigned as the next node (i.e. the last node in the reversed list) in the second last iteration (of your original loop).
private static Node reverseList(Node head) {
Node reverseHead = getLastNode(head);
Node reference = reverseHead;
int counter = listSize;
while ( counter > 1) {
Node temp = getPreviousNode(reference, head);
Node last = getLastNode(reverseHead);
temp.next = null;
last.next = temp;
reference = temp;
counter--;
}
return reverseHead;
}
Secondly, you shouldn't modify your listSize variable directly because the number of elements in the reversed list remains the same. Here, I'm storing it in a temporary counter first before iterating the list.
And, finally the reversed list should become your current head. Since, you've modified the linking between all the elements, it can only be traversed if your head now points to the new head.
printNodeValues(head);
head = reverseList(head);
printNodeValues(head);
In this specific instance, it takes into account two occasions. One where I'm trying to place a node in the beginning of the Linked List and one where I'm trying to place it in the middle or at the end. Here is my Node Class. If you look at my INSERT method, the part that is not working is:
Node newNode = new Node();
newNode.setExponent(element);
class Node {
private int coefficient;
private int exponent;
private Node link;
// Constructor: Node()
Node(int c, int e) {
// Sets coefficient to c, exponent to e, and link to null
coefficient = c;
exponent = e;
link = null;
}
// Inspectors: getCoefficient(), getExponent(), getLink()
public int getCoefficient() {
// Returns coefficient
return coefficient;
}
public int getExponent() {
// Returns exponent
return exponent;
}
public Node getLink() {
// Returns link
return link;
}
// Modifiers: setCoefficient(), setExponent(), setLink()
public void setCoefficient(int c) {
// Sets coefficient to c
coefficient = c;
}
public void setExponent(int e) {
// Sets exponent to e
exponent = e;
}
public void setLink(Node n) {
// Sets link to n
link = n;
}
}// Ends Node Class
Here is where I'm trying to insert to my Linked List along with some other methods in the class that should help give you an idea of how my code looks.
class List {
private Node head; // Points to first element of the list
private int count; // number of elements in the list
// Constructor:
List() {
// Sets head to null and count to zero
head = null;
count = 0;
}
// Inspectors:
// Returns the number of elements in the list
public int size() {
return count;
}
// Modifiers:
// Inserts element at index in the list. Returns true if successful
public boolean insert(int index, Node element) {
if (index < 0 || index > count)return false;
if (index == 0) {
Node newNode = new Node();
newNode.setExponent(element);
count++;
newNode.setLink(head);
head = newNode;
return true;
}
Node walker = head;
for (int i = 1; i < (index - 1); i++)
walker = walker.getLink();
Node newNode = new Node();
newNode.setExponent(element);
newNode.setLink(walker.getLink());
walker.setLink(newNode);
count++;
return true;
}
Try this:
Assumption: You are trying to insert a Node element into the index of LinkedList
Your insert method with modification.
public boolean insert(int index, Node element) {
//if (index < 0 || index > count)
if (index < 0 || index > count + 1) return false;
if(head == null) {
head = element;
return true;
}
if (index == 0) {
//Node newNode = new Node();
//newNode.setExponent(element);
count++;
element.setLink(head);
//newNode.setLink(head);
head = element;
//head = newNode;
return true;
}
Node walker = head;
//for (int i = 0; i < (index - 1); i++)
for (int i = 1; i < index; i++) {
walker = walker.getLink();
}
//Node newNode = new Node();
//newNode.setExponent(element);
element.setLink(walker.getLink());
//newNode.setLink(walker.getLink());
//walker.setLink(newNode);
walker.setLink(element);
count++;
return true;
}
Sample Test Case:
print method:
void print() {
Node travel = head;
while(travel!= null) {
System.out.println(travel.getExponent() + " " + travel.getCoefficient());
travel = travel.getLink();
}
}
Main method:
public static void main(String args[]) {
Node n1 = new Node(1,2);
List l = new List();
l.insert(0,n1);
Node n2 = new Node(3,2);
l.insert(1,n2);
Node n3 = new Node(4,5);
l.insert(0,n3);
l.print();
}