I have a non-cyclic linked list data structure. Like this:
public class LinkLst<T>{
private Node<T> first;
public LinkLst(T t){
first = new Node(t);
}
}
public class Node<T>{
private T t;
private Node<T> next;
public Node(T t){
this.t = t;
}
public void setNext(Node<T> n){
this.next = next;
}
}
So we know by default the List contains no cycles. Is there a way to find a n-th element from the end of LinkLst<T> lst
with only one iteration if n <= size(lst)
and throw IndexOutOfBoundException
if n > size(lst)
.
public <T> T fromTheEnd(LinkLst<T> lst, int n){
//...?
}
The only thing I could find is to reverse it and then find the desired element, but it requires 2 iterations. One for reverse and one to find the desired element. Also memory overhead.
public <T> T fromTheEnd(LinkList<T> ts, int idx) {
Node<T> follower, leader;
// We iterate until the leader hits the end of the list. follower follows leader
// idx steps behind, so when leader.next = [], follower is the desired node.
follower = leader = ts.first;
for(int j = 0; j < idx; j++) {
leader = leader.next;
}
// leader is now idx steps ahead
while(leader.next != null) {
leader = leader.next;
follower = follower.next;
}
// leader has hit the end (next is null)
// follower has your data
return follower.t;
}
In essence, this is a single iteration with two "heads."
Example of indexing 2
into [1, 2, 3, 4, 5]
, from the end.
Setup:
[1, 2, 3, 4, 5]
^ Leader
^ Follower
First loop:
[1, 2, 3, 4, 5]
^ F ^ L
Second loop round 0:
[1, 2, 3, 4, 5]
^ F ^ L
Second loop round 1:
[1, 2, 3, 4, 5]
^ F ^ L
Loop ends: next(leader) = []
deref(follower) = 3
You'll probably want to factor out the method <T> LinkList<T> last(LinkList<T>, int)
that returns the suffix of the list with the given length, which lets you express fromTheEnd
as just last(ts, n).first.t
.
If you don't want to iterate twice, you'd have to remember n
values, which requires memory. Whether that's better than iterating twice is for you to decide.
Create an array of size n
, and add values to array in a cyclic manner as you iterate the list.
When reaching end of list, and at least n
elements have been iterated, the nth-from-last element is in the next position of the cyclic array.
This sacrifices memory for performance.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.