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.
Related
I have seen similar questions asked, but none of the answers really address my confusion.
I'm working through some Linked List content, trying to write methods to solve leetcode-like problems. I'm working with singly-linked lists, defined as:
public class LinkedListy {
ListNode head;
LinkedListy(){};
public static class ListNode {
int val; //integer variable
ListNode next; //pointer
ListNode() {}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val; this.next = next;
}
}
...
I'm trying to write a function that will reverse my linked list, but will not destroy my original linked list. The code I have written works to reverse the list, but destroys the original list:
public ListNode reverse() {
//use copyList function to avoid altering head --> DOESN'T WORK
ListNode current = head;
ListNode temp = null;
ListNode copied_result = null;
while(current != null){
temp = current.next;
current.next = copied_result;
copied_result = current;
current = temp;
}
return copied_result;
}
From reading on here and other places, I understand that by setting current = head, I'm just creating a new reference for the same ListNode. Thus, when I run my code, I'm mutating the original list.
Main Confusion: I'm confused because I have written methods that do NOT destroy the original list, but use the same kind of reference to head. For example, in my "length()" method, I set dummy = head and alter dummy to find the length of the list. But, then the original list doesn't get changed (I wrote a print function to print the list and I verified it prints the same before and after calling length().)
public int length() {
ListNode dummy = head;
int length = 0;
while(dummy != null) {
dummy = dummy.next;
length++;
}
return length;
}
So, I'm clearly not understanding something fundamental about LinkedLists.
Why does my reverse() method destroy the original list when my length() method does not?
Is the only way to write a reverse method for a linked list without destroying the original list to make a copy of the original list in your main method and reverse the copy?
Any help or resources would be greatly appreciated. Thanks!
In the length method, you're using a locally accessible variable named dummy to iterate through the nodes in the list; when you set dummy = dummy.next, this sets the value of the local variable to refer to the next node. This is very different from doing something like dummy.next = null, which would affect the content of node to which dummy currently refers.
To that end, your reverse method doesn't actually 'destroy' the original list - the main issue is that head isn't being set to the first element when you're finished. Thus, head still 'points' to the same node it did before the function started, which is now the last node.
If you want to reverse the list in-place, then just updating head properly at the end of your function will work fine - if you want to return a reversed copy of your original list without modifying the original, you'll need to copy all of the nodes. See #Hank_interprize's description of deep/shallow copies.
I believe the issue here is you are not actually copying any new information over to the new list but instead the code is just using the same list as before under a new name. This can be done with a deep copy.
To create a new list you will need to copy the old data over to a new list with a whole new system of pointers and simply copying the data over to the new linked list which is different than copying the pointer.
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.
I have checked few posts that we have in SO.
Insert new node at the beginning of Linked-List
How do I insert a node at the beginning of a linked list?
And implemented a simple LinkedList in java that works just fine.
What I can't get my head around is how adding a new Node to the beginning of the LinkedList would actually work.
Here is how my code snippet for adding a Node to the beginning of the LinkedList looks like:
public class SinglyLinkedList
{
//Private variable to keep tab of the HEAD of the linked list.
private ListNode head;
//Private variable to keep track of the node count in this singly linked list.
private int length;
.
.
.
/**
* Insert a ListNode at the beginning of this List.
*/
public synchronized void insertAtBegin(ListNode newNode)
{
//Set current head as the next of input ListNode
newNode.setNext(head);
//Set the input ListNode as the new head of this SinglyLinkedList
head = newNode;
//Increment the SinglyLinkedList length
length++;
}
.
.
.
}//End of class SinglyLinkedList
The ListNode class represents a Single Node like so:
/**
* Represents a Node of the Linked List.
*/
public class ListNode
{
private ListNode next;
private int data;
/**
* Constructors
*/
public ListNode()
{
next = null;
data = Integer.MIN_VALUE;
}
public ListNode(int data)
{
next = null;
this.data = data;
}
/**
* Accessor methods.
*/
public int getData()
{
return this.data;
}
public void setData(int data)
{
this.data = data;
}
public ListNode getNext()
{
return next;
}
public void setNext(ListNode listNode)
{
this.next = listNode;
}
public String toString()
{
return Integer.toString(data);
}
}//End of class ListNode
The 2 lines that really confuse me are:
//Set current head as the next of input ListNode
newNode.setNext(head);
//Set the input ListNode as the new head of this SinglyLinkedList
head = newNode;
The more I try to analyze these two lines, I feel it will create a circular reference structure instead of pushing in the "newNode" in place of "head".
May be I don't quite understand how Java references are passed around.
Is there an explanation as to why the above two lines won't end up in a circular reference?
It seems you understand conceptually how the LinkedList gets a new head node. Your question is more related to Java itself.
Remember that Java is pass-by-value; When you are passing objects around, you aren't passing the value of the object - you are passing the value of the pointer to that object. Is Java "pass-by-reference" or "pass-by-value"?
So with that in mind, let me break down those 2 lines.
newNode.setNext(head)
The value in head is a pointer to a node. So the setNext function is receiving, in accordance to pass-by-value, a pointer to a node. It is NOT receiving a pointer to head.
head = newNode;
in this line, we reassign head's VALUE to be a POINTER to the newly created node. The value in newNode.next is still a pointer to the previous head.
You are encountering a very common confusion with Java, and believe me it is VERY VERY common (hence the 2k upvotes on the SO I referenced above). I hope this addresses your main source of confusion!
Imagine you have the following LinkedList:
2 -> 3 -> 4 -> 5
and you want to insert a node with a value of 1 at the beginning. Let's call this node newNode.
Now look at this line: newNode.setNext(head); You are making newNode's next value point to head, which in this case is pointing to the node with a value of 2. This is what your list looks like now:
1 -> 2 -> 3 -> 4 -> 5
However, head is still pointing to the node with the value of 2, so you have to fix that by making head point to the node with a value of 1, which is newNode. That is what the line head = newNode; does.
When your list is moving from right to left, i.e. 1 then after new node insertion it becomes 2->1 then after fresh insertion it becomes 3->2->1, In this case you need to take care of two things only : head (the first element of the list) & temporary node which is to be inserted next. Here is the pseudo code for that:
` while(you_want_to_insert_new_node) //temporary is the node to be inserted freshly
{
Insert(temporary->data); //Insert data in temporary node
temporary->next=head;
head=temporary;
}
`
When your list is moving from left to right, i.e 1->2 then it becomes 1->2->3 and so on, you need to take care of 3 things: head, the current node and the temporary. Here is the pseudo code for that:
`
current=head;
while(you_want_to_insert_new_node) //temporary is the node to be inserted freshly
{
Insert(temporary->data); //Insert data in temporary node
current->next = temporary;
current=temporary;
}
i'm writing a method using linked list to delete even number indexes from the list (i'm not using List<object> list = new LinkedList<object>() <--- i know this is kinda easier.., i'm implementing node class in this problem (which i'm really confused at right now.)
Well, the problem tells me to delete the even number indexes from a List, and return a new List. But i don't know what to do here (this method is in LinkedIntList class that also contains ListNode class)? And please check my code if it's right or what i can do to improve. Thanks.
public ????????? removeEvens() {
ListNode current = front;
while(current.next!= null) {
current = current.next.next;
}
return ???????????;
}
EDIT: i've tried NodeList but it still give me an error so i guess i'll post a pic.
Since you want to return a new List, the return type should be a ListNode or a LinkedList.
public ListNode removeEvens(){
ListNode current = front;
//Since we are setting current's next to current.next.next, we need to make
//sure that we don't get a null point exception.
while(current.next!=null){
//removes all event nodes.
current.next = current.next.next;
current = current.next;
}
return current;
}
A LinkedList can be represented by a ListNode. If you want to return a LinkedList, simply change the return type of the function and return a new LinkedList with the current list node passed into the constructor.
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