patternjavaMinor
Reverse sublists of a linked list
Viewed 0 times
sublistslistlinkedreverse
Problem
This code reverses each consecutive n elements of a linked list, and for spare nodes, leaves them as they are.
For example, the linked list
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
for an interval of 3 should result in
3 -> 2 -> 1-> 6 -> 5 -> 4 -> 7
Note that 7 is left as it is as its spare.
I'm looking for code review, optimization and best practices.
```
public class ReverseAtInterval implements Iterable {
private Node first;
private Node last;
private int size;
public ReverseAtInterval(List c) {
for (T item : c) {
add(item);
}
}
public void add (T t) {
final Node l = last;
final Node node = new Node(t, null);
last = node;
if (first == null) {
first = node;
} else {
l.next = node;
}
size++;
}
private static class Node {
T item;
Node next;
Node(T item, Node next) {
this.item = item;
this.next = next;
}
}
private static class ReversedFirstLastNextData {
Node first; // first node in the reversed list.
Node last; // last node in the reversed list.
Node next; // next node - this node is not a part of revered list
public ReversedFirstLastNextData(Node first, Node last, Node next) {
this.first = first;
this.last = last;
this.next = next;
}
}
private ReversedFirstLastNextData reverse(Node start, int n) {
Node prev = null;
Node ptr = start;
Node ptr1 = null;
int ctr = 0;
while (ctr (prev, start, ptr);
}
public void reverseAtInterval(int n) {
int ctr = 0;
ReversedFirstLastNextData prev = null;
ReversedFirstLastN
For example, the linked list
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
for an interval of 3 should result in
3 -> 2 -> 1-> 6 -> 5 -> 4 -> 7
Note that 7 is left as it is as its spare.
I'm looking for code review, optimization and best practices.
```
public class ReverseAtInterval implements Iterable {
private Node first;
private Node last;
private int size;
public ReverseAtInterval(List c) {
for (T item : c) {
add(item);
}
}
public void add (T t) {
final Node l = last;
final Node node = new Node(t, null);
last = node;
if (first == null) {
first = node;
} else {
l.next = node;
}
size++;
}
private static class Node {
T item;
Node next;
Node(T item, Node next) {
this.item = item;
this.next = next;
}
}
private static class ReversedFirstLastNextData {
Node first; // first node in the reversed list.
Node last; // last node in the reversed list.
Node next; // next node - this node is not a part of revered list
public ReversedFirstLastNextData(Node first, Node last, Node next) {
this.first = first;
this.last = last;
this.next = next;
}
}
private ReversedFirstLastNextData reverse(Node start, int n) {
Node prev = null;
Node ptr = start;
Node ptr1 = null;
int ctr = 0;
while (ctr (prev, start, ptr);
}
public void reverseAtInterval(int n) {
int ctr = 0;
ReversedFirstLastNextData prev = null;
ReversedFirstLastN
Solution
You and @bazang are both very much into interview-questions, and I think you would benefit greatly from answering each others' questions. In fact, writing reviews would be more useful for preparing you for interviews than asking yet more questions, because:
I bring this up now, because @bazang has tried to solve… exactly the same problem!
Review
I agree with @Anonymous that your architecture is much too complicated, with too many inner classes.
It's odd that your
Passing the list to the
If you try to reverse a list with an interval that is greater than the length of the input list, you get a
Proposed Solution
Here's what I came up with. (It's completely different from the solution for @bazang because you chose to base your interface on
ReverseAtInterval.java
ReverseAtIntervalTest.java
- You get "no" choice in the matter of which question you are presented — just like in a real interview (assuming you commit yourself to answering whatever question comes your way).
- You practice communication skills, which are also important for interviewing.
- When you review someone else's work, you gain an appreciation for what goes on in the mind of the interviewer.
I bring this up now, because @bazang has tried to solve… exactly the same problem!
Review
I agree with @Anonymous that your architecture is much too complicated, with too many inner classes.
It's odd that your
ReverseAtInterval() constructor takes a List, but you also offer the option to add individual elements via public add(T). The state problem was to reverse a list — so don't complicate things by offering to handle more stuff.Passing the list to the
ReverseAtInterval() constructor, then passing the interval to .reverseAtInterval() is also odd. Calling .reverseAtInterval() will rearrange everything in the new order. Allowing that mutated list to be further mutated if one calls .reverseAtInterval() again is more likely to be misused than useful.If you try to reverse a list with an interval that is greater than the length of the input list, you get a
NullPointerException..toArray() is misnamed. I would expect it to return an array, not a List.Proposed Solution
Here's what I came up with. (It's completely different from the solution for @bazang because you chose to base your interface on
java.util.List.)ReverseAtInterval.java
import java.util.*;
public class ReverseAtInterval implements Iterable {
private final List list;
private final int interval;
public ReverseAtInterval(List list, int interval) {
if (interval iterator() {
return new SublistReversingIterator();
}
//////////////////////////////////////////////////////////////////////
private class SublistReversingIterator implements Iterator {
// Iterator for the underlying list
private final Iterator underIter = ReverseAtInterval.this.list.listIterator();
private final LinkedList group = new LinkedList();
private Iterator groupIter = group.iterator();
public boolean hasNext() {
return this.groupIter.hasNext() || this.underIter.hasNext();
}
public T next() {
if (!this.groupIter.hasNext()) {
if (!this.underIter.hasNext()) {
throw new NoSuchElementException();
}
try {
for (int i = interval; i > 0; i--) {
this.group.push(this.underIter.next());
}
this.groupIter = group.iterator();
} catch (NoSuchElementException exhausted) {
// For spare nodes, leave them as they are. In other
// words, reverse the group again to restore the original
// order.
this.groupIter = group.descendingIterator();
}
}
try {
return groupIter.next();
} finally {
groupIter.remove();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}ReverseAtIntervalTest.java
import static java.lang.System.out;
public class ReverseAtIntervalTest {
public static void main(String[] args) {
List oneFive = Arrays.asList(new Integer[] {1, 2, 3, 4, 5});
for (int interval = 1; interval (oneFive, interval)) {
out.print(elem); out.print(' ');
}
out.println();
}
// IllegalArgumentException expected...
new ReverseAtInterval(oneFive, 0);
}
}Code Snippets
import java.util.*;
public class ReverseAtInterval<T> implements Iterable<T> {
private final List<T> list;
private final int interval;
public ReverseAtInterval(List<T> list, int interval) {
if (interval < 1) throw new IllegalArgumentException("interval < 1");
this.list = list;
this.interval = interval;
}
public Iterator<T> iterator() {
return new SublistReversingIterator();
}
//////////////////////////////////////////////////////////////////////
private class SublistReversingIterator implements Iterator<T> {
// Iterator for the underlying list
private final Iterator<T> underIter = ReverseAtInterval.this.list.listIterator();
private final LinkedList<T> group = new LinkedList<T>();
private Iterator<T> groupIter = group.iterator();
public boolean hasNext() {
return this.groupIter.hasNext() || this.underIter.hasNext();
}
public T next() {
if (!this.groupIter.hasNext()) {
if (!this.underIter.hasNext()) {
throw new NoSuchElementException();
}
try {
for (int i = interval; i > 0; i--) {
this.group.push(this.underIter.next());
}
this.groupIter = group.iterator();
} catch (NoSuchElementException exhausted) {
// For spare nodes, leave them as they are. In other
// words, reverse the group again to restore the original
// order.
this.groupIter = group.descendingIterator();
}
}
try {
return groupIter.next();
} finally {
groupIter.remove();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}import static java.lang.System.out;
public class ReverseAtIntervalTest {
public static void main(String[] args) {
List<Integer> oneFive = Arrays.asList(new Integer[] {1, 2, 3, 4, 5});
for (int interval = 1; interval <= 6; interval++) {
for (int elem : new ReverseAtInterval<Integer>(oneFive, interval)) {
out.print(elem); out.print(' ');
}
out.println();
}
// IllegalArgumentException expected...
new ReverseAtInterval<Integer>(oneFive, 0);
}
}Context
StackExchange Code Review Q#51183, answer score: 6
Revisions (0)
No revisions yet.