I have a question, I've looked around on the internet but couldn't find an example. But making a String trim() method in java (remove lead/trailing whitespace), I know the basic code for this is:
public LString trim(){
int i = this.size;
int j = 0;
int k = this.offset;
char[] arrayOfChar = this.data;
while ((j < i) && (arrayOfChar[(k + j)] <= ' '))
++j;
while ((j < i) && (arrayOfChar[(k + i - 1)] <= ' '))
--i;
return (((j > 0) || (i < this.size)) ? substring(j, i) : this);
}
But, how would you write this same method, but applied to a linked list? More specifically, a linked list that uses a Node class.
Here is what I did....correct me if this is wrong...I'll include relevant class information that pertains to the question.
public class LString{
private Node front = null; //first val in list
private Node back; //last val in list
private int size = 0;
private int i;
private int offset;
public LString(){
//construct empty list
Node LString = new Node();
front = null;
}
.......//skip down some methods to this one
//returns new lstring that is slice of lstring
//contains an endIndex as well
public LString substring(int beginIndex, int endIndex){
Node current = this.front;
int size = 0;
while(current != null && size < beginIndex){
size++;
current = current.getNext();
}
front = new Node();
front.setData(current.getData());
Node ocurrent = front;
while(current != null && size < endIndex){
current = current.getNext();
Node curr2 = new Node();
curr2.setData(current.getData());
ocurrent.setNext(curr2);
ocurrent = curr2;
size++;
}
ocurrent.setNext(null); //set next val to null to term string
return this;
}
public LString trim(){
String lstr;
int i = this.size;
int m = this.offset;
int k = charAt(m);
Node current = front;
while(current != null){
current = current.getNext();
if(current.data > '\u0020'){
return this;
} else if(current.data < '\u0020'){
LString lstring = new LString(); //this worked!?
return lstring;
}
}
return this.substring(k, m+1);
}
...............................................................
//My Node class:
public class Node{
public char data;
public Node next;
//constructors from page 956
public Node()
{
this('\0',null); //'\0' is null char for java
}
public Node(char initialData, Node initialNext)
{
data = initialData;
next = initialNext;
}
}
(If you are unfamiliar with the node class, it basically just creates a singly linked node to use as your links between data in your linked list class)
I've never seen an example or anything, so I thought I'd ask the community.
Assuming that
by trimming the list you want to remove leading and trailing elements that are null
and under "linked list that uses a Node class" you mean java.util.LinkedList
You should keep in mind that in java internal implementation of LinkedList is not exposed (note: java.util.LinkedList.Node has private access modifier), all modifications are performed through methods of iterator and LinkedList itself.
Implementation would be:
public static void trim (LinkedList list){
if (list == null || list.size() == 0) return;
Object element = null;
ListIterator i = list.listIterator();
while (i.hasNext() && element == null) {
element = i.next();
if (element == null) {
i.remove();
}
}
element = null;
i = list.listIterator(list.size());
while (i.hasPrevious() && element == null) {
element = i.previous();
if (element == null) {
i.remove();
}
}
}
However if you are reimplementing mutable strings via linked list as an exercise
(if not as an exercise then stop right there and use StringBuilder or StringBuffer), then, assuming that you implement it with doubly linked list, it will go like this:
EDIT: my bad, you can iterate to the first non-empty element and set reference directly to it, updated algorithm
Fetch first element
While fetched element is empty fetch next
Set head reference to the last fetched element, set last fetched element's prev reference to null
Fetch last element
While fetched element is empty fetch previous
Set tail reference to the last fetched element, set last fetched element's next reference to null
UPDATE With code you provided try something like this (since you are using singly-linked list, it is slightly different then the one described above):
public void trim(){
//early out if empty
if (front == null || back==null) return;
Node current = front;
//looking for the first non-empty element
while(current != null && current.data<'\u0020' ){
current = current.next;
}
//left trim
this.front = current;
//looking for last non-empty element
while (current!=null&¤t.next!=null&¤t.next.data>'\u0020'){
current = current.next;
}
//right trim
this.back = current;
if (current!=null){
current.next = null;
}
}
Assuming you just want to trim each String in a LinkedList, why not just iterate over each item?
LinkedList<String> myNodes = new LinkedList<String>();
myNodes.add('This is a node ');
myNodes.add(' another node '));
for (String s : myNodes){
s.trim();
}
Related
public static SinglyLinkedListNode insertNodeAtPosition(SinglyLinkedListNode llist, int data, int position) {
if(llist == null) {
llist = new SinglyLinkedListNode(data);
return llist;
} else {
for (int i = 0; i < position-1; i++) {
llist = llist.next;
}
SinglyLinkedListNode temp = llist;
llist.next = new SinglyLinkedListNode(data);
llist = llist.next;
llist.next = temp.next;
return llist;
}
}
This is my code to place a custom index node in LinkedList. But hackerrank is not accepting my code. What's wrong with my algorithm?
The problem is that your code always returns the newly created node, but you should always return the first node in the list, which either is what it was when you got it, or is the new node in case the position was zero.
What to look at:
I'll not provide the corrected code, but will give you two hints:
By moving llist ahead in the for loop, you lose the reference to that first node, so use a different variable for walking through the list.
Also, you should deal specifically with the case where position is 0, as this is the only case where the returned value is not the original llist value, but the new node's reference, much like you have in the if block.
Easiest solution No need of explaination :
Solution :
static SinglyLinkedListNode insertNodeAtPosition(SinglyLinkedListNode head, int data, int position) {
if (head == null) return null;
SinglyLinkedListNode temp = new SinglyLinkedListNode(data);
if (position == 0) {
temp.next = head;
return temp;
}
SinglyLinkedListNode p = head;
for (int i = 0; i< position-1; i++) {
p = p.next;
}
SinglyLinkedListNode next = p.next;
p.next = temp;
temp.next = next;
return head;
}
The problem requires you to return a linked list. When we are asked to return a linked list, actually we return the first node of the linked list.
So, your problem is the returned value in your code script is not the first node of the linked list.
The simplest solution is that you keep the first node in another variable, and
return that variable after you have done the insert thing.
for example:
SinglyLinkedListNode dumyNode = llist;
......
return dumyNode;
Suppose given the correct Node class, you can try this approach (without index collision case):
private Node find(int index) {
Node curr = head;
for (int i = 0; i < index; i++)
curr = curr.next;
return curr;
} // end find()
public Object get(int index) throws IndexOutOfBoundsException {
if (index >= 0 && index < size) {
Node curr = find(index);
return curr.data;
} else {
throw new IndexOutOfBoundsException();
} // end if - else
} // end get()
public void add(Object data, int index) throws IndexOutOfBoundsException {
if (index >= 0 && index < size + 1) {
if (index == 0)
head = new Node(data);
else {
Node prev = find(index - 1);
prev.next = new Node(data);
} // end if - else
size++;
} else {
throw new IndexOutOfBoundsException();
} // end if - else
} // end add()
Hello all so I have a linked list here and I have to make a remove method that works properly. For example if I call remove(0) it should delete the first thing that was entered in the list and so on and so forth. This is a little bit different than most linked lists because usually the head node is at the 0ith place however in this case the head is at the end of the list. So my code so far works pretty good however I am unable to delete the head node or the last item in my list. Also if my list only has one element in it, it is also unable to be deleted. My code works for all other cases I have looked at examples for deleting the head node however it doesn't seem to work in my case. If anyone can help me out it would be greatly appreciated!
public class MyLinkedList {
private MyNode head;
private int numberElements;
public MyLinkedList() {
numberElements = 0;
head = null;
}
// runtime = \Theta(1)
// if you don't care about ordering
// every time something is inserted it becomes the head node
public void insert(MyCircle m) {
MyNode temp = new MyNode();
temp.setData(m);
temp.setNext(head);
head = temp;
numberElements++;
}
// runtime = \Theta(n)
public void remove(int index) {
if (index >= numberElements || index < 0) {
throw new RuntimeException("Index too big or too small!");
}
MyNode current = head;
if (index == numberElements) {
head = head.getNext(); // I have seen this in other examples to delete the head node. However It does not work for mine.
}
int length = numberElements - index - 2;
for (int i = 0; i < length; i++) {
current = current.getNext();
}
if (index != 0 && index != numberElements) {
current.setNext(current.getNext().getNext());
} else if (index == 0) {
current.setNext(null);
}
numberElements--;
}
// runtime = \Theta(n)
public void print() {
// loop through the list until getNext is null
MyNode current = head;
while (current != null) {
System.out.println(current.getData());
current = current.getNext();
}
}
}
I figured it out. A simple - 1 had to be added.
MyNode current = head;
if (index == numberElements ** - 1 **) {
head = head.getNext(); // I have seen this in other examples to delete the head node. However It does not work for mine.
}
Here is the beginning of the class if it helps at all. I'm trying to write a method to remove an element from a specific index in the doubly linked list. I'm not sure if I'm remotely on the right path but this is what i've done and I'm getting a NullPointerException at:
prevNode.next = nextNode;
public class DoublyLinkedList {
Node start;
Node end;
int length;
public DoublyLinkedList() {
this.start = null;
this.end = null;
this.length = 0;
}
public void removeAtIndex(int index) {
Node currentNode = start;
for (int i = 0; i < index; i++) {
if (index < 0 || index > length) {
System.out.println("The index is out of bounds");
return;
} else if (currentNode == null) {
System.out.println("The list is empty");
return;
} else if (i == index - 1) {
Node nextNode = currentNode.next;
Node prevNode = currentNode.prev;
prevNode.next = nextNode;
nextNode.prev = prevNode;
return;
}
currentNode = currentNode.next;
}
}
With your flow, it is return null because the currentNode is null at first.
Let's take a look at your code. (I guess you've started programing, right :P)
Move out the check IndexOutOfBounds from the for, nothing to do with for loop here.
Your idea about remove item at i by set pre node linked to next node, It is OK, and i see your code is fine.
I hope that you have implemented the addNode to increase the length, because it will not go into the for loop.
Once again, check out your code and clear your mind. Many return is not really good.
This how you would add an item:
public void insert (Object item)
{
Link add = new Link();
add.data = item;
add.next = head;
_head = add;
++_listsize;
}
But how do you add an item at a given position. So far this is what I got:
public void insert (Object item, int pos)
{
Link add = new Link();
int ix = pos - 1;
add.next = _head;
for (int i = _listsize - 1; i >= ix; --i)
add = add.next;
add.data = item;
_head = add;
++_listsize;
}
This will insert the item correctly if it is sequential, but let say I am given a position which is in the middle, what it will do it will insert the item but it will completely cut off (or delete the rest). For example:
insert at 1:
a
insert at 2:
b
a
insert at 3:
c
b
a
insert at 2:
d
a
You should do something like this:
public void insert (Object item, int pos)
{
Link add = new Link();
int ix = pos - 1;
Link cur = _head;
for (int i = 0; i < _list_size; i++) {
if(i == ix) {
add.next = cur.next;
cur.next = add;
}
cur = cur.next;
}
++_listsize;
}
It seems you have not correctly inserted the new Link into the list. When you do that, you need to find the Link at the given position as well as the Link at the previous position. Then only you can set the previous.next = add and add.next = position.
Below is the updated method that does the task.
public void insert (Object item)
{
Link add = new Link();
add.data = item;
add.next = _head;
_head = add;
++_listsize;
}
public void insert (Object item, int pos)
{
Link add = new Link();
add.data = item;
int ix = pos - 1;
add.next = _head;
Link previous = _head;
for (int i = _listsize - 1; i > ix; --i) {
previous = previous.next;
}
Link position = previous.next;
previous.next = add;
add.next = position;
++_listsize;
}
Use add( int index, E element), which insert the element at the specified index : http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#add(int, E)
EDIT : if you're using LinkedList, of course ; with your own class, you have to store prev/next pointers and simply update them (previous node next's pointer should point to the new element, and next node previous's pointer should point to the new element too)
It is definetly possible. But what would matter most is deciding at which position to insert new element because after each insertion the list would change and position of new element coming will have to be decided appropriately. You can try this
insertat=head;
for(i=0;i<pos;i++){
insertat=insertat.next;
}
add.next=insertat.next;
insertat.next=add;
listsize++;
You need a temporary variable that start from the head, traverse each node until the desired position or the end of the list, then insert the new node.
Since it is a homework exercise, I will only post pseudo code:
if pos < 0
//define what to do here...
return
end if
if pos == 0
//inserting at the beginning
insert(item)
return
end if
Link temp <- head
int index <- 0
while index < pos and temp->next != null
temp <- temp->next
index <- index + 1
end while
//now you're at your desired location or at the end of the list
Link newLink <- new Link
newLink->data <- item
newLink->next <- temp->next
temp->next <- newLink
After attempting alone the implementation of the concept, you can consider the open-source research. One of the best things you can do with open source is learn from it, study the implementation of java.util.LinkedList,
following the logic of the method add (int index, E element) { http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/LinkedList.java#360 }, you can divide in;
1) Get where the element will be added, in your case "link"
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/LinkedList.java#380
2) and you can examine the code that links the elements following the logic "before adding" in the code snippet
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/LinkedList.java#794
So, you will understand the logic behind the algorithm and will be able to perform your own implementation
My solution is not as clean as it will be with recursion but if you are testing more than 50,000 elements on the list go with an iterative solution. or you can modify the JVM and change the stack size.
Because you can get a stack overflow just because you will pass the capacity of activation records in the stack. Think about the worst case scenario that you will do an insert at the end of the list.
/**
* Inserts the specified element at the specified position in this list.
*
* #param :index the desire position starting from 0 2,3,4,5
* #param :data the content of the new node
* #return Boolean: if the insertion was successfully return true otherwise false
*/
public boolean add(int index, T data) {
/*Add to the end of the list*/
if (index == size()) {
add(data);
return true;
}
/*Empty list and index bigger than 0*/
else if (this.front == null && index != 0) {
return false;
} else {
Node<T> tempNode = this.front;
while (tempNode != null && tempNode.next != null && --index != 0) {
tempNode = tempNode.next;
}
if (index != 0) {
return false;
} else {
Node<T> newNode = new Node<T>(data);
/*Empty list,and index is 0*/
if (tempNode == null) {
this.front = newNode;
} else {
newNode.next = tempNode.next;
tempNode.next = newNode;
}
}
}
return true;
}
I am trying to remove an item from the LinkedList in java. This List is implemented by me and I am not using any java API. The major trouble I am facing is with RECURSION as I am always lost in recursion coding.
class List{
int N;
List next;
List current;
List(int N){
this.N =N;
this.next = null;
}
#Override
public String toString() {
String o = "";
List curr = this;
while(curr != null){
o += curr.N+"-->";
curr = curr.next;
}
return o+"TAIL";
}
}
Method implemented:
private static List Remove(List L,int N){
if(L == null || L.next == null)
return L;
List current = L;
List previous = null;
while(current != null){
if(current.N == N){
current = current.next;
if(previous == null)previous = current;
else{
previous.next = current;
}
break;
}else{
previous = current;
current = current.next;
}
}
return previous;
}
Input -
List list1 = new List(1);
list1.next = new List(2);
list1.next.next = new List(3);
list1.next.next.next = new List(4);
list1.next.next.next.next = new List(5);
list1.next.next.next.next.next = new List(6);
list1.next.next.next.next.next.next = new List(7);
System.out.println("Before Removal "+list1.toString());
System.out.println("After Removal "+Remove(list1,3));
Output I am getting is -
Before Removal 1-->2-->3-->4-->5-->6-->7-->TAIL
After Removal 2-->4-->5-->6-->7-->TAIL
Here I am losing the value 1 as I am setting the current = current.next or reference is being set to next value. So definitely I am having some problem with the presentation of data stored in different references.
The mistake is here:
return previous;
You should return the original head of the list if it was not removed. To show it graphically:
N == 3
List Before Removal: 1-->2-->3-->4-->5-->6-->7-->TAIL
At start of iteration 1:
L ^
previous (null)
current ^
No match -> iteration 2:
L ^
previous ^
current ^
No match -> iteration 3:
L ^
previous ^
current ^
Match -> remove current:
List After Removal: 1-->2-->4-->5-->6-->7-->TAIL
L ^
previous ^
current ^
At this point by returning previous, you lose the former head element L.
For the case when the head element is to be removed, you should add a separate check before the loop.
Btw your Remove method is not recursive - it is never calling itself.
It's simply because you are not returning the head - but instead the previous pointer to the node you just 'removed':
static List Remove(final List L, final int N) {
// Base case for null head pointer
final List head = L;
if (head == null)
return head;
// Base case for removing the head
if (head.N == N)
return head.next;
List current = head.next;
List previous = head;
while (current != null) {
if (current.N == N) {
current = current.next;
if (previous == null) {
previous = current;
}
else {
previous.next = current;
}
break;
} else {
previous = current;
current = current.next;
}
}
return head;
}
Also - to clarify - this is not a recursive solution.