I am tring to insert string into doubly linked list in reverse order. But I am not sure how can I maintain the insertion order in reverse order.
This is my below code.
theList.insertReverseLexicographicalOrder("B");
theList.insertReverseLexicographicalOrder("A");
theList.insertReverseLexicographicalOrder("H");
theList.insertReverseLexicographicalOrder("D");
theList.insertReverseLexicographicalOrder("E");
public void insertReverseLexicographicalOrder(String dd) {
Link newLink = new Link(dd);
if (isEmpty()){
last = newLink;
}
first.previous = newLink;
}
newLink.next = first;
first = newLink;
}
Any suggestions will be appreciated with some code based on my solution..
Well you assume that its already in reverse order, so you're going to need some sort of loop through until you find where it should go.. i.e.
Z, Y, X, W, L, K, A
if you're inserting M, then you should loop until you find L, which is lexicographically larger than M, and therefore insert it there. Because the nodes have previous pointers, insertion shouldn't be too hard to figure out on your own
You would need to look through the list comparing each of the elements. Stop when you find the element that goes after the element you are trying to insert. I suggest you implement the compareTo method in your node class: http://www.javapractices.com/topic/TopicAction.do?Id=10
and use it to make the comparisons
Good Luck.
How to insert a node into a linked list:
If the list is empty, the new node will become the first, and if we keep track of that, also the last
Otherwise find the position where to insert, there are three possibilities,
a) the new node has to be inserted before the first
b) the new node has to be inserted after the last
c) the new node has to be inserted between two existing nodes
Update the appropriate references, that may be first, last and some next and previous fields, depending on where it has to be inserted
if (first == null) {
// the list is empty so far
} else
To find the position, first compare the data with the first node's data to see whether it has to be inserted before the first node.
if (newLink.iData.compareTo(first.iData) > 0) {
// put newLink before first
} else {
You have to keep a focus on some list node. Follow the list from the start until you reach the point of insertion:
Link focus = first; // focus first node
while(focus.next != null && newLink.iData.compareTo(focus.next.iData) < 0) {
focus = focus.next;
}
// now you have to insert the new value behind focus, left as exercise
if (focus.next == null) {
// newLink becomes the last node in the list
} else {
// newLink has to be inserted between focus and focus.next
}
}
Then insert. Beware of edge cases, inserting at the front and the end are slightly different.
Related
I am currently doing a Cracking the Coding Interview Problem (2.4) and I am supposed to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. However, I am really confused as to why a temporary variable "next" is needed and why is node.next nulled below it. Why can't I just do node = node.next at the end of the while loop?
I am simply creating two linked lists, before and after, and merging them together once the correct values are put into each list.
public static Node partition(Node node, int x) {
Node beforeStart = null;
Node beforeEnd = null;
Node afterStart = null;
Node afterEnd = null;
/* Partition list */
while (node != null) {
Node next = node.next;
node.next = null;
if (node.data < x) {
if (beforeStart == null) {
beforeStart = node;
beforeEnd = beforeStart;
} else {
beforeEnd.next = node;
beforeEnd = beforeEnd.next;
}
} else {
if (afterStart == null) {
afterStart = node;
afterEnd = afterStart;
} else {
afterEnd.next = node;
afterEnd = afterEnd.next;
}
}
node = next;
}
/* Merge before list and after list */
if (beforeStart == null) {
return afterStart;
}
beforeEnd.next = afterStart;
return beforeStart;
}
Why can't I just do node = node.next at the end of the while loop?
It can be done this way. After doing the partition, for each list, you need to set the last node's next pointer to NULL. This will just take two lines of code.
The example code is using next = node.next and node.next = NULL to terminate each list during the partition process, but in this case that's not needed, since the lists don't need NULL terminators until after the partition process is done.
The loop in your question removes nodes from the head of the original list, and appends them to the before list or the after list, until the original list is empty. Then it concatenates the before and after lists.
That's easy to explain and easy to understand.
It can be done without the temporary next or nulling out node.next in every iteration, but then the above description would no longer apply -- nodes would not be removed from the original list in every iteration, the before list and after list would not contain only the appropriate nodes, the operation you perform on them is not 'appending', and nodes would even appear in multiple lists for a while.
Your algorithm would suddenly be a lot more difficult to describe and understand. That is a bad thing in software development, and a bad thing in a coding interview.
If the title is not confusing enough maybe this will be. I have a linked list which contains people who have first and last names as well as a few other variables. The list must be sorted by last name first, then by first name. So far I insert the people into the list in alphabetical order by last name. I then try to traverse the list, if two last names are the same, I check the first names and swap. But I have a bug.
Inserted alphabetically into the list by last name, last,first
Acy,Mary
Acy,Clayton
Bob,Lonnie
Toni,Lonnie
After my so call "sort" of first names
Acy,Mary
Bob,Lonnie
Acy,Clayton
Toni,Lonnie
You can see it is sorted by last name. I am trying to sort each same last name by first name. And this is what I get as output from
public void sortFirstNames(){
System.out.println("here");
PeopleNode previous = null;
PeopleNode current = head;
PeopleNode temp;
if(head == null || head.next == null){
return;
}
while(current != null && current.next != null && current.lastName.compareTo(current.next.lastName) == 0){ //traverse the list
if((current.firstName).compareTo(current.next.firstName) > 0){ //see which first name goes first
temp = current.next.next;
current.next.next = temp.next;
temp.next = current.next;
current.next = temp;
current = temp.next;
}
current = current.next;
}
}
It doesn't change the list at all, I have taken advise of commenters but have yet to make it work. Does anyone have any idea?
Basically I am trying to say while two last names are the same check the first names, then swap them if need be.
The heart of your problem lies here:
if(previous.firstName.compareTo(current.firstName) >= 0){
temp = current;
current = previous;
previous = temp;
}
Firstly - >=. That's probably not so much a problem as just unnecessary - there's no need to swap elements that are equal - just make it > instead.
Next, that code doesn't change the linked-list at all. All it does is change the values of the local variables, so previous ends up pointing to the node after current in the actual linked-list, and then, because of the >=, if you have equal values, you'll just continuously process the same two nodes.
This post elaborates a bit on that: Is Java "pass-by-reference" or "pass-by-value"?
What you need to do is compare something.next and something.next.next (no need for 2 separate variables), and then you can swap these, which will change the linked-list.
I know this is a duplicate problem but my question is different.
Help me to understand few lines of this code.It removes duplicate nodes from a single linked list.
public class DeleteDuplicates {
static void deleteDups(LinkedListNode n) {
Hashtable table = new Hashtable();
LinkedListNode previous = null;
while(n!=null) {
if(table.containsKey(n.data)) {
previous.next = n.next;
} else {
table.put(n.data, true);
previous = n;
}
System.out.println(n.next.data);
n = n.next;
}
}
public static void main(String[] args) {
LinkedListNode node_1 = new LinkedListNode("first");
LinkedListNode node_2 = new LinkedListNode("second");
node_1.next = node_2;
LinkedListNode node_3 = new LinkedListNode("third");
node_2.next = node_3;
LinkedListNode node_4 = new LinkedListNode("second");
node_3.next = node_4;
LinkedListNode current = node_1;
deleteDups(current);
while (current != null) {
System.out.println(current.data);
current = current.next;
}
}
}
Questions I have are:
How come LinkedList n is skipping the duplicate node? I didn't understand the use of previous node and how it is helping in skipping the duplicate node.
How important is the use of Hashtable? Can I use any other collection for example HashSet?
You already have good answers to your question 2, so I'll just concentrate on question 1 (really you should only ask 1 question in each post, by the way). This is how the removal of the duplicate works:
In each iteration through your loop, previous holds a reference to the node in the list before the node n. So, when n is set to your node_4, previous is set to node_3. Therefore, previous.next = n.next is equivalent to node_3.next = node_4.next, which because you don't set a value for node_4.next is equivalent to node_3.next = null, which has the effect of making node_3 the last node in the list, thus removing node_4 from the list.
If, instead of node_4 being the duplicate, it was node_3 that was duplicated, then previous would be node_2, n would be node_3 and the change made would be equivalent to node_2.next = node_3.next, which is to say node_2.next = node_4 or in plain English, "make the next node after node_2 be node_4", effectively removing node_3 from the list.
1) LinkedList is not skipping the duplicate node, it is being mapped out - next is pointed to the entry after the duplicate.
2) Think LinkedList allows duplicates, but Hashtable does not -> make your conclusion from this
You can use any data structure you like for detecting duplicates.
From an implementation point of view, hashes are nice because they take (amortized) constant time to determine whether or not a particular element is a duplicate.
From an API point of view, the Collection.Set interface is nice because it guarantees no duplicate items.
So your idea of using a HashSet seems very intuitive, especially because you're only interested in duplicate keys, without regard for the actual node object.
I know it is a minute code. I can't understand why my linked list reversal is not working.
Can some one help fix me my reverse method in the below code.
//Reverse a single linked list
public Node reverse()
{
return reverse(root);
}
private Node reverse(Node node)
{
Node previous = null;
Node current = node;
Node forward;
while (current != null)
{
forward = current.next;
current.next = previous;
previous = current;
current = forward;
}
return previous;
}
Any input on this would be helpful
Thanks !!!
I'm pretty sure it should be
return root = reverse(root);
(Your reverse logic is correct, but if the root is still pointing at the old root of the list, you will end up with a 1-element linked list.)
Assuming homework...
Write simple tests: list of 0 items, list of 1 items, list of 2 items, list of 10 items. Than make sure each of them work - will narrow down error and learn to write unit tests.
Are you sure you're using the returned value of reverse() to do your iteration instead of root?
i have a question about circularly linked lists. My linked list object has two references, first and last, and the next node of the last reference is first. I want to write a method that inserts a node into the end of the list.
void insertLast(int k) {
Node a = new Node(k);
if (first == null) {
first = last = a;
} else {
last.after = a;
a.after = first;
}
last = a
}
Is something like this possible? Have I made a mistake?
Yes, it is.
let the current last point to the new one (last.setNext(newNode))
let the new one point to the first (newNode.setNext(first))
set the last to be the new node (last = newNode)