Optimal ways to Traverse through a LinkedList - Java - java

The Situation
I have a interview with TripAdvisor tomorrow and I decided for practice to create my own custom LinkedList. I'm trying to figure out the best way to traverse through it.
Primary Question: I have managed to traverse through my Linked List however I believe
there is a better way to do it. How would you traverse through it ?
Bonus Question: How do my overall classes look ? Is there anything I should/should not add ?
It seems to work fine but is it optimal ?
Bonus Question #2: Lastly I was wondering if anyonehad any insight to typical interview questions/concepts that I must know ?
Greatly appreciated.
Here are my Classes
// *********************************Node Class*******************************************
public class Node<T> {
Node<T> link;
T data;
public Node(T data) {
this.data = data;
link = null;
}
public T getData() {
return data;
}
public Node<T> getLink() {
return link;
}
public Node<T> setLink(Node<T> N) {
this.link = N;
return link;
}
public void setData(T newData) {
this.data = newData;
}
}
//****************************************Linked List Class*******************************
public class LinkedList<T> {
Node<T> head;
T data;
public LinkedList(){
head = null;
}
public void add(T data){
Node<T> newNode = new Node<T> (data);
newNode.setLink(head);
head = newNode;
}
//had problems printing out the data in the last node
public void traverse(){
Node<T> pointer;
pointer = head;
while (pointer.getLink()!=null){
System.out.println(pointer.getData());
pointer = pointer.setLink(pointer.getLink());
}
//Fixed problems For last node that doesnt get printed out
System.out.println(pointer.getData());
}
//Again is there a better way to do this ?
//Thanks
}

I would change your traverse function to be more like this:
public void traverse(){
Node<T> pointer = head;
while (pointer != null){
System.out.println(pointer.getData());
pointer = pointer.getLink();
}
}
Also it is common to represent the Node class as a private inner class of LinkedList because it is not typically needed anywhere else.
As far as the interview itself goes, traversal questions are more typical for binary-trees (eg. print out the elements in sorted order). LinkedList questions are more focussed on the remove/insert operations which both require careful attention to the edge cases (what happens when you remove the head for example). A more advanced LinkedList question would ask how to detect a cycle, I would make sure that I knew at least one method of doing this (have a look at the Tortoise and the Hare algorithm).
EDIT:
Algorithm questions will nearly always be from the following list:
String manipulation such as:
Reverse String
Count how many times each letter appears in a given String (use a Map for this)
LinkedList questions such as:
How to remove a node, pay close attention to edge cases such as removing the head
How to reverse a linkedList (make the Tail the Head)
Binary Tree questions such as:
In-order traversal
If there is a BTree balancing question you won't need to implement it, just understand that a completely unbalanced Binary Tree is simply a Linked List.
Understand that searching a balanced Binary Tree is O(log n) compared to a Linked List or a completely unbalanced Binary Tree which is O(n).
You will probably be asked to describe the complexity of the solution you just gave (big-O notation)
See this and this for questions related to Java itself

Related

How can I inverse a list of elements if I can only access to an element and his next one?

I have been given a "class" called LinkedList which has only one atributte
"Node first" which refers to the first element of a list. The way to access the other ones is that class "Node" has access to an element 'x' and his following one:
public class LinkedList<T> {
private static class Node<E> {
E elem;
Node<E> next;
Node (E elem) {
this.elem = elem;
this.next = null;
}
}
private Node<T> first;
So that, I have been ordered to do a method called "reverse" from class "LinkedList" which has to reverse the list. However, the difficulty of the exercise is that I can only re-link the attributte "first", I mean I cannot create auxiliar data structures and that type of help.
I have done this in order to achieve the last element of the list, but I dont know how to continue:
public void reverse () {
Node<T> aux = first.next;
while (aux.next != null) {
first.elem = aux.elem;
aux = aux.next;
}
first.elem = aux.elem;
}
It seems quite a theoretical question to me, so you might want to check Geek for Geeks first. Most of these questions that are used in programming courses are well explained there, including coding examples.
In this case, a well-known solution is to use three pointers: a current number, the previous number , and the next number; to keep track of nodes to update reverse links.
Check here: https://www.geeksforgeeks.org/reverse-a-linked-list/

Pointers in LinkedList in Java

I am studying the linked lists,and I'm having a little problem understanding references and pointers in Java (and also have some questions for which I can't find answer on the internet.) Namely,I have a class LinkedList that uses class Node like this:
public class LinkedList {
public Node head;
public LinkedList(int data) {
head = new Node(data);
}
}
and this is my Node class:
public class Node {
public int data;
public Node next;
public Node(int data2) {
data = data2;
}
}
I also have method toStringLL() inside LinkedList which looks like:
public void toStringLL() {
LinkedList l=this;
while(l.head.next != null) {
System.out.print(l.head.data+"->");
l.head = l.head.next;
}
System.out.print(l.head.data);
System.out.println("");
}
I don't understand why this toStringLL() changes my head of linked list,when I am iterating through it with l.head=l.head.next? Shouldn't my head stay the same?I thought that when I write LinkedList l=this,I can freely iterate through l,without affecting this(or am I wrong?) Now when I use Node n=this.head instead of LinkedList l=this,it works,but I have difficulty figuring out why that works and the previous doesn't.. Can someone explain to me the difference between these two?
I don't understand why this toStringLL() changes my head of linked list,when I am iterating through it with l.head=l.head.next?Shouldn't my head stay the same?
When you make the assignment
LinkedList l = this;
you are not creating a new LinkedList object. You are just defining a references to the existing LinkedList object.
Therefore, l.head = l.head.next does exactly the same as this.head = this.head.next. Both change your original list.
On the other hand, when you write
Node n = this.head
you are not changing the head of your List. You are declaring a variable that initially refers to the head of your List, but when you change that variable to refer to other Nodes of your list, the head variable of your list (this.head) remains unchanged.
When you set
l.head=l.head.next;
you change your head.

Coding conventions for Linked Lists

I have been implementing this interview question in Java . A fairly simple problem with an additional constraint of size :
Find the Nth Node from the end of a Linked List where the size of the Linked List is unknown?
I am not concerned with the solution to this problem,because I have already figured that out.
Instead, I want to know whether my implementation maintains the coding conventions which experienced coders maintain while coding a problem related to Linked Lists and it's implementation?.Here is my implementation of the above problem:
import java.io.*;
class NthNodeFromEnd<AnyType>
{
private Node<AnyType> head;
private Node<AnyType> pointer;
private class Node<AnyType>
{
protected AnyType item;
protected Node<AnyType> next;
}
void push(AnyType item)
{
if(isEmpty())
{
head = new Node<AnyType>();
head.item = item;
head.next = null;
pointer = head;
}
else
{
Node<AnyType> newNode = new Node<AnyType>();
newNode.item = item;
newNode.next = null;
pointer.next = newNode;
pointer = pointer.next;
}
}
boolean isEmpty()
{
return head == null;
}
AnyType printNthLastNode(int n)
{
Node<AnyType> ptr1 = head;
Node<AnyType> ptr2 = head;
for(int i =0;i<n;i++)
{
ptr1 = ptr1.next;
}
while(ptr1!=null)
{
ptr1 = ptr1.next;
ptr2 = ptr2.next;
}
return ptr2.item;
}
public static void main(String args[])
{
NthNodeFromEnd<Integer> obj = new NthNodeFromEnd<Integer>();
obj.push(1);
obj.push(2);
obj.push(3);
obj.push(4);
obj.push(5);
obj.push(6);
obj.push(7);
System.out.println("The nth item is = "+obj.printNthLastNode(5));
}
}
P.S. - I am aware of the fact that there is an inbuilt implementation of Linked List in Java, but I don't want to use that.I want to know whether this implementation of the problem is good enough or is there a better way to tackle Linked List related problems?
Regarding the code conventions:
generic types are typically defined as a single uppercase letter: E or T, but not AnyType, which looks like a concrete type.
operators should be surrounded by spaces, semi-colons followed by a space, etc. For example, for(int i =0;i<n;i++) should be for (int i = 0; i < n; i++)
A method printNthLastNode() should print the nth last node, not return it. A method returning it should be named getNthLastNode() or findNthLastNode(). BTW, this method doesn't return a node, but a value stored in the list.
methods should generally not be package-private. They should be public or private generally.
the usual convention in Java is to have opening curly braces at the end of the line, and not at the beginning of the next line.
your method printNthLastNode() will fail with a NPE if the list is empty or not large enough. A better exception type should be used to signal this problem.
the class should not import java.io.*, since it doesn't use any class from java.io. packages should generally not be imported. Classes should.
String[] args is more readable than String args[], and is more conventional.
the Node class should be static: it doesn't use any instance member of its enclosing type.
That said, the interviewer should see, with the code posted, that you understand how a linked list works and how pointers work, as well as generic types.

Building Singly LinkedList

I am attempting to build a data structure in Java with inner list that are made up of singly link lists that contain integers. I am having trouble with the architecture of my data structure. It needs to have a inner class with functions that can merge, split, and give the size of the inner lists.
Assume that the size of the inner lists will change and size and data will be removed to consolidate and optimize the data structure.
I have a driver class to interface with the data structure. Then I have a Data structure class which will have the inner class.
Where do I put methods to add/remove top level lists as the singly linked list collapses and expands with my data??
How many classes should I have? A driver, the data structure(with inner class)... more?
I just need a little direction from someone who is a strong coder, I made multiple attempts at top down designs, and I have read and searched. I just need some direction. I attached and image of how the data structure looks.
PLEASE NOTE:
The inner lists must be implemented as a singly-linked lists with dummy headers and tail pointers, and I must not use any data structures from Java Collections API for the inner lists. For the top-level list, I have to use the generic LinkedList class from the Java Collections API.
Note: This looks like a homework, otherwise there would be no need to reinvent the wheel. Knowing this, I won't provide specific code, just pseudocode (except for some keywords like class, int and similar), no useful methods like getters or setters, no additional fields, etc. It will be your job to generate all the necessary Java code to make this work.
I don't know where to start, I am new to linked lists
Start by defining the structure of the elements that will go inside the list. How to do this? Review the requirement (emphasys mine):
build a data structure in Java with inner list that are made up of singly link lists that contain integers
You need a data structure that at first can hold an integer value and behaves as singly linked list. From the definition of singly linked list, the structure contains two elements:
The integer data to hold
The pointer to the next similar data structure.
This can be addressed like this:
class DataStructure {
int data;
DataStructure next;
}
Now that you have the structure that supports the singly linked list, you need a new structure that will be the singly linked list and define the behavior of it. This can be addressed as stated in your requirements:
The inner lists must be implemented as a singly-linked lists with dummy header and tail pointers
Moving this into pseudocode:
class SinglyLinkedList {
DataStructure head;
DataStructure tail;
}
That's it. Now that you have your SinglyLinkedList, you just need to define the behavior. Again, reviewing the requirements:
It needs to have a inner class with f̶u̶n̶c̶t̶i̶o̶n̶s̶ methods that can merge, split, and give the size of the inner lists.
From here, we can define at least three methods for the SinglyLinkedList data structure: merge, split and size. Adapting the latest class from it:
class SinglyLinkedList {
DataStructure head;
DataStructure tail;
//added this method just to know you need to add data to your singly linked list
public void add(int data) {
}
//you merge a list with another list
public void merge(SinglyLinkedList singlyLinkedList) {
}
//you split the list into two or more lists
public SinglyLinkedList[] split() {
}
//the size of the list is a numeric positive value
public int size() {
}
}
EDIT (based on your edit and by looking at the picture)
There's the need to define another data structure that holds a list of singly linked lists. By requirements:
For the top-level list, I have to use the generic LinkedList class from the Java Collections API.
Then, you just need a new structure that uses a LinkedList that will contain your singly linked lists:
class SinglyLinkedListHolder {
LinkedList<SinglyLinkedList> holder;
public SinglyLinkedListHolder () {
holder <- new LinkedList<SinglyLinkedList>();
}
//this holder should at least add new singlyLinkedList in the bigger list
public void add(SinglyLinkedList singlyLinkedList) {
}
}
Note: I notice that you tried to define your structure with generics:
private static class Node<T> {
}
I highly recommend you to not do this until you really grasp the main concepts about how a singly linked list works. It can take some time, but it is better to go step by step. After making this structure to work, then you can easily (in fact, depending on your implementation) replace the structure to:
class DataStructure<T> {
T data;
DataStructure next;
}
public class LL {
class Node
{
String data;
Node next;
Node(String data)
{
this.data=data;
this.next=null;
}
}
public Node head;
public void add_first(String data)
{
Node NewNode=new Node(data);
if(head == null)
{
head=NewNode;
return;
}
NewNode.next=head;
head=NewNode;
}
public void add_last(String data)
{
Node NewNode=new Node(data);
if(head==null)
{
head=NewNode;
return;
}
Node currentNode =head;
while(currentNode.next !=null)
{
currentNode=currentNode.next;
}
currentNode.next=NewNode;
}
public void insert_pos(String data,int pos)
{
Node NewNode=new Node(data);
Node current=head;
for(int i=0;i<pos-1;i++)
{
System.out.println("Current is"+current.data);
current=current.next;
}
System.out.println(current.data);
NewNode.next=current.next;
current.next=NewNode;
System.out.println("Delete Element Successfuly at position"+pos);
}
int counter;
public void size()
{
Node current=head;
if(head==null)
{
System.out.println("Linked list is Empty.......");
}
while(current!=null)
{
current=current.next;
counter+=1;
}
System.out.println("Linked list size is:"+counter);
}
public void display()
{
Node cur=head;
while(cur!=null)
{
System.out.print(cur.data+"->");
cur=cur.next;
}
System.out.println("null");
}
public void delete_first()
{
Node temp=head;
head=temp.next;
System.out.println("Delete First Element Successfuly");
}
public void delete_last()
{
Node current=head;
Node lastnode=head.next;
while(lastnode.next!=null)
{
current=current.next;
lastnode=lastnode.next;
}
current.next=null;
System.out.println("Delete last Element.");
}
public void delete_pos(int pos)
{
Node current=head;
Node last=head.next;
for(int i=0;i<pos-1;i++)
{
System.out.println("Current is"+current.data);
current=current.next;
last=last.next;
}
current.next=last.next;
}
public static void main(String[] args)
{
LL list=new LL();
list.add_last("A");
list.add_last("B");
list.add_last("C");
list.add_last("d");
list.add_last("e");
// list.delete_pos(3);
//list.delete_first();
//list.delete_last();
// list.insert_pos("nirav",4);
list.size();
list.display();
}
}

Linear linked list, prepend node

I have a problem understanding an exercise. I have to develope a linear linked list. But I do not have to to distinguish between list and node.
The constructor Node should create a node and prepend it to the list that is passed as a parameter.
Normally I would go through the list and append a node at the end of it. Here is my code.
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);
}
}
Maybe I have just learned to much today and my brain can't take more inforamtion:D please help!
You need modify the next pointer of the node to point to the list that is passed in as a parameter.
This is in fact what your code is already doing. I have tried running it and it gives the correct result. :)
You might want to consider including a separator in your implementation of toString so that the output is still clear when the numbers in the data get larger than 9.
I am not sure what you are asking but i think this is what you want so here it goes.
Lets say you already have the head
Node head = ...
you can append to this by doing
head = new Node(..., head)
Notice I am assigning head again so now the head points to the newly created node.

Categories