How to remove the Nth node from the end of a linked list?











up vote
1
down vote

favorite












This is the data structure I am using to represent a single linked list:



type Link = Option<Box<Node>>;

pub struct Node {
elem: i32,
next: Link,
}


I would like to implement a method to remove the Nth node from the end of the list:



// Original list
A -> B -> C -> D -> None

// remove 1 from the end of the original list
A -> B -> C -> None

// Remove 2 from the end of the original list
A -> B -> D -> None


I am fighting with the borrow checker all the time:



fn remove_nth_node_from_end(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let mut i = 0;
let mut fast = list;
while let Some(ref mut node) = {fast} {
if i == n {
break;
}
i += 1;
fast = &mut node.next;
}

// issues start here, since I need to mutably borrow
// the list (and it has already been moved above for fast)
// but without moving I have troubles implementing the above loop
let mut slow = &mut list;
// iterate over the list using slow and fast
// when fast is None
// slow.next = slow.next.next
}


error[E0596]: cannot borrow immutable argument `list` as mutable
--> src/lib.rs:25:25
|
25 | let mut slow = &mut list;
| ^^^^ cannot borrow mutably
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
|
25 | let mut slow = list;
| ^^^^

error[E0382]: use of moved value: `list`
--> src/lib.rs:25:25
|
13 | let mut fast = list;
| -------- value moved here
...
25 | let mut slow = &mut list;
| ^^^^ value used here after move
|
= note: move occurs because `list` has type `&mut std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait


How can I implement the remaining part of the method?



Please note my methods does not take self as argument and the list argument needs to be moved twice at least with the current implementation.










share|improve this question
























  • I believe your question is answered by the answers of Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If you disagree, please edit your question to explain the differences. Otherwise, we can mark this question as already answered.
    – Shepmaster
    Nov 10 at 18:29










  • See also the 26 previous questions that are linked to the suggested duplicate
    – Shepmaster
    Nov 10 at 18:31










  • Especially Deleting a node from singly linked list has the error “cannot move out of borrowed content”
    – Shepmaster
    Nov 10 at 18:32










  • @Shepmaster The first link you provided does what I do with the fast "pointer", but my problem arises when I need to follow also the slow pointer, because the anchor/head has been moved already.
    – Nick
    Nov 10 at 18:34






  • 1




    On reflection, I think I would instead write that as *list = list.take().and_then(|l| l.next);. You should familiarize yourself with Option's methods; there is often a conversion that does just what you want. and_then returns None if list.take() is None, so this version of remove_helper won't panic if you call it with an empty list and n of zero.
    – trentcl
    Nov 11 at 0:01

















up vote
1
down vote

favorite












This is the data structure I am using to represent a single linked list:



type Link = Option<Box<Node>>;

pub struct Node {
elem: i32,
next: Link,
}


I would like to implement a method to remove the Nth node from the end of the list:



// Original list
A -> B -> C -> D -> None

// remove 1 from the end of the original list
A -> B -> C -> None

// Remove 2 from the end of the original list
A -> B -> D -> None


I am fighting with the borrow checker all the time:



fn remove_nth_node_from_end(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let mut i = 0;
let mut fast = list;
while let Some(ref mut node) = {fast} {
if i == n {
break;
}
i += 1;
fast = &mut node.next;
}

// issues start here, since I need to mutably borrow
// the list (and it has already been moved above for fast)
// but without moving I have troubles implementing the above loop
let mut slow = &mut list;
// iterate over the list using slow and fast
// when fast is None
// slow.next = slow.next.next
}


error[E0596]: cannot borrow immutable argument `list` as mutable
--> src/lib.rs:25:25
|
25 | let mut slow = &mut list;
| ^^^^ cannot borrow mutably
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
|
25 | let mut slow = list;
| ^^^^

error[E0382]: use of moved value: `list`
--> src/lib.rs:25:25
|
13 | let mut fast = list;
| -------- value moved here
...
25 | let mut slow = &mut list;
| ^^^^ value used here after move
|
= note: move occurs because `list` has type `&mut std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait


How can I implement the remaining part of the method?



Please note my methods does not take self as argument and the list argument needs to be moved twice at least with the current implementation.










share|improve this question
























  • I believe your question is answered by the answers of Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If you disagree, please edit your question to explain the differences. Otherwise, we can mark this question as already answered.
    – Shepmaster
    Nov 10 at 18:29










  • See also the 26 previous questions that are linked to the suggested duplicate
    – Shepmaster
    Nov 10 at 18:31










  • Especially Deleting a node from singly linked list has the error “cannot move out of borrowed content”
    – Shepmaster
    Nov 10 at 18:32










  • @Shepmaster The first link you provided does what I do with the fast "pointer", but my problem arises when I need to follow also the slow pointer, because the anchor/head has been moved already.
    – Nick
    Nov 10 at 18:34






  • 1




    On reflection, I think I would instead write that as *list = list.take().and_then(|l| l.next);. You should familiarize yourself with Option's methods; there is often a conversion that does just what you want. and_then returns None if list.take() is None, so this version of remove_helper won't panic if you call it with an empty list and n of zero.
    – trentcl
    Nov 11 at 0:01















up vote
1
down vote

favorite









up vote
1
down vote

favorite











This is the data structure I am using to represent a single linked list:



type Link = Option<Box<Node>>;

pub struct Node {
elem: i32,
next: Link,
}


I would like to implement a method to remove the Nth node from the end of the list:



// Original list
A -> B -> C -> D -> None

// remove 1 from the end of the original list
A -> B -> C -> None

// Remove 2 from the end of the original list
A -> B -> D -> None


I am fighting with the borrow checker all the time:



fn remove_nth_node_from_end(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let mut i = 0;
let mut fast = list;
while let Some(ref mut node) = {fast} {
if i == n {
break;
}
i += 1;
fast = &mut node.next;
}

// issues start here, since I need to mutably borrow
// the list (and it has already been moved above for fast)
// but without moving I have troubles implementing the above loop
let mut slow = &mut list;
// iterate over the list using slow and fast
// when fast is None
// slow.next = slow.next.next
}


error[E0596]: cannot borrow immutable argument `list` as mutable
--> src/lib.rs:25:25
|
25 | let mut slow = &mut list;
| ^^^^ cannot borrow mutably
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
|
25 | let mut slow = list;
| ^^^^

error[E0382]: use of moved value: `list`
--> src/lib.rs:25:25
|
13 | let mut fast = list;
| -------- value moved here
...
25 | let mut slow = &mut list;
| ^^^^ value used here after move
|
= note: move occurs because `list` has type `&mut std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait


How can I implement the remaining part of the method?



Please note my methods does not take self as argument and the list argument needs to be moved twice at least with the current implementation.










share|improve this question















This is the data structure I am using to represent a single linked list:



type Link = Option<Box<Node>>;

pub struct Node {
elem: i32,
next: Link,
}


I would like to implement a method to remove the Nth node from the end of the list:



// Original list
A -> B -> C -> D -> None

// remove 1 from the end of the original list
A -> B -> C -> None

// Remove 2 from the end of the original list
A -> B -> D -> None


I am fighting with the borrow checker all the time:



fn remove_nth_node_from_end(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let mut i = 0;
let mut fast = list;
while let Some(ref mut node) = {fast} {
if i == n {
break;
}
i += 1;
fast = &mut node.next;
}

// issues start here, since I need to mutably borrow
// the list (and it has already been moved above for fast)
// but without moving I have troubles implementing the above loop
let mut slow = &mut list;
// iterate over the list using slow and fast
// when fast is None
// slow.next = slow.next.next
}


error[E0596]: cannot borrow immutable argument `list` as mutable
--> src/lib.rs:25:25
|
25 | let mut slow = &mut list;
| ^^^^ cannot borrow mutably
help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
|
25 | let mut slow = list;
| ^^^^

error[E0382]: use of moved value: `list`
--> src/lib.rs:25:25
|
13 | let mut fast = list;
| -------- value moved here
...
25 | let mut slow = &mut list;
| ^^^^ value used here after move
|
= note: move occurs because `list` has type `&mut std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait


How can I implement the remaining part of the method?



Please note my methods does not take self as argument and the list argument needs to be moved twice at least with the current implementation.







list rust






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 18:44

























asked Nov 10 at 18:21









Nick

3,3311057123




3,3311057123












  • I believe your question is answered by the answers of Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If you disagree, please edit your question to explain the differences. Otherwise, we can mark this question as already answered.
    – Shepmaster
    Nov 10 at 18:29










  • See also the 26 previous questions that are linked to the suggested duplicate
    – Shepmaster
    Nov 10 at 18:31










  • Especially Deleting a node from singly linked list has the error “cannot move out of borrowed content”
    – Shepmaster
    Nov 10 at 18:32










  • @Shepmaster The first link you provided does what I do with the fast "pointer", but my problem arises when I need to follow also the slow pointer, because the anchor/head has been moved already.
    – Nick
    Nov 10 at 18:34






  • 1




    On reflection, I think I would instead write that as *list = list.take().and_then(|l| l.next);. You should familiarize yourself with Option's methods; there is often a conversion that does just what you want. and_then returns None if list.take() is None, so this version of remove_helper won't panic if you call it with an empty list and n of zero.
    – trentcl
    Nov 11 at 0:01




















  • I believe your question is answered by the answers of Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If you disagree, please edit your question to explain the differences. Otherwise, we can mark this question as already answered.
    – Shepmaster
    Nov 10 at 18:29










  • See also the 26 previous questions that are linked to the suggested duplicate
    – Shepmaster
    Nov 10 at 18:31










  • Especially Deleting a node from singly linked list has the error “cannot move out of borrowed content”
    – Shepmaster
    Nov 10 at 18:32










  • @Shepmaster The first link you provided does what I do with the fast "pointer", but my problem arises when I need to follow also the slow pointer, because the anchor/head has been moved already.
    – Nick
    Nov 10 at 18:34






  • 1




    On reflection, I think I would instead write that as *list = list.take().and_then(|l| l.next);. You should familiarize yourself with Option's methods; there is often a conversion that does just what you want. and_then returns None if list.take() is None, so this version of remove_helper won't panic if you call it with an empty list and n of zero.
    – trentcl
    Nov 11 at 0:01


















I believe your question is answered by the answers of Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If you disagree, please edit your question to explain the differences. Otherwise, we can mark this question as already answered.
– Shepmaster
Nov 10 at 18:29




I believe your question is answered by the answers of Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If you disagree, please edit your question to explain the differences. Otherwise, we can mark this question as already answered.
– Shepmaster
Nov 10 at 18:29












See also the 26 previous questions that are linked to the suggested duplicate
– Shepmaster
Nov 10 at 18:31




See also the 26 previous questions that are linked to the suggested duplicate
– Shepmaster
Nov 10 at 18:31












Especially Deleting a node from singly linked list has the error “cannot move out of borrowed content”
– Shepmaster
Nov 10 at 18:32




Especially Deleting a node from singly linked list has the error “cannot move out of borrowed content”
– Shepmaster
Nov 10 at 18:32












@Shepmaster The first link you provided does what I do with the fast "pointer", but my problem arises when I need to follow also the slow pointer, because the anchor/head has been moved already.
– Nick
Nov 10 at 18:34




@Shepmaster The first link you provided does what I do with the fast "pointer", but my problem arises when I need to follow also the slow pointer, because the anchor/head has been moved already.
– Nick
Nov 10 at 18:34




1




1




On reflection, I think I would instead write that as *list = list.take().and_then(|l| l.next);. You should familiarize yourself with Option's methods; there is often a conversion that does just what you want. and_then returns None if list.take() is None, so this version of remove_helper won't panic if you call it with an empty list and n of zero.
– trentcl
Nov 11 at 0:01






On reflection, I think I would instead write that as *list = list.take().and_then(|l| l.next);. You should familiarize yourself with Option's methods; there is often a conversion that does just what you want. and_then returns None if list.take() is None, so this version of remove_helper won't panic if you call it with an empty list and n of zero.
– trentcl
Nov 11 at 0:01














1 Answer
1






active

oldest

votes

















up vote
0
down vote



accepted










This is how you could write the method without using recursion.



fn remove_nth(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let get_length = |l: &Link| {
let mut length = 0;
let mut current = l;
while let Some(n) = {current} {
length += 1;
current = &n.next;
}
length
};
let length = get_length(list);
let mut i = 0;
let mut current = list;
while i < length - n {
if let Some(link) = {current} {
current = &mut link.next;
} else {
panic!("Invalid node!");
}
i += 1;
}
*current = current.as_mut().unwrap().next.take();
}


Unfortunately, I didn't manage to make the borrow checker happy by using the more efficient runner pattern.






share|improve this answer

















  • 1




    @Stargateur of course recursion is less efficient, since space complexity would be O(N) compared to the O(1) of the runner pattern.
    – gliderkite
    Nov 11 at 10:18






  • 1




    Every iterative function can be write in the form of tail recursive function, what you are saying is completely false. recursion can do this in O(1) like iterative can do this in O(1). Everything iterative can do recursive can and vice versa.
    – Stargateur
    Nov 11 at 11:20








  • 1




    @Stargateur If you were to rewrite this recursively, you'd have to write two recursive algorithms, because it contains two loops. My recursive solution traverses the list only once, but at the cost of O(n) space. So that is the comparison being made here, not recursion vs. iteration in general.
    – trentcl
    Nov 11 at 13:39










  • I think by "runner pattern" gliderkite means the algorithm OP was trying to use, i.e. two pointers that traverse the list n nodes apart. When the first pointer reaches the end, the second pointer is pointing at the node to be removed. But to be honest... I don't really see how this solution is more efficient than that. Perhaps I'm missing something.
    – trentcl
    Nov 11 at 13:41






  • 1




    Pheraps I didn't explain myself well. My solution is less efficient than the runner pattern the OP was trying to use, because it needs to iterate in the worst case twice the list (to get its length first), while using the runner pattern you only need to iterate the list once. Nevertheless it's still O(N) time complexity and O(1) space complexity, while the recursive solution is O(N) for both (time and space).
    – gliderkite
    Nov 11 at 14:00













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242052%2fhow-to-remove-the-nth-node-from-the-end-of-a-linked-list%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
0
down vote



accepted










This is how you could write the method without using recursion.



fn remove_nth(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let get_length = |l: &Link| {
let mut length = 0;
let mut current = l;
while let Some(n) = {current} {
length += 1;
current = &n.next;
}
length
};
let length = get_length(list);
let mut i = 0;
let mut current = list;
while i < length - n {
if let Some(link) = {current} {
current = &mut link.next;
} else {
panic!("Invalid node!");
}
i += 1;
}
*current = current.as_mut().unwrap().next.take();
}


Unfortunately, I didn't manage to make the borrow checker happy by using the more efficient runner pattern.






share|improve this answer

















  • 1




    @Stargateur of course recursion is less efficient, since space complexity would be O(N) compared to the O(1) of the runner pattern.
    – gliderkite
    Nov 11 at 10:18






  • 1




    Every iterative function can be write in the form of tail recursive function, what you are saying is completely false. recursion can do this in O(1) like iterative can do this in O(1). Everything iterative can do recursive can and vice versa.
    – Stargateur
    Nov 11 at 11:20








  • 1




    @Stargateur If you were to rewrite this recursively, you'd have to write two recursive algorithms, because it contains two loops. My recursive solution traverses the list only once, but at the cost of O(n) space. So that is the comparison being made here, not recursion vs. iteration in general.
    – trentcl
    Nov 11 at 13:39










  • I think by "runner pattern" gliderkite means the algorithm OP was trying to use, i.e. two pointers that traverse the list n nodes apart. When the first pointer reaches the end, the second pointer is pointing at the node to be removed. But to be honest... I don't really see how this solution is more efficient than that. Perhaps I'm missing something.
    – trentcl
    Nov 11 at 13:41






  • 1




    Pheraps I didn't explain myself well. My solution is less efficient than the runner pattern the OP was trying to use, because it needs to iterate in the worst case twice the list (to get its length first), while using the runner pattern you only need to iterate the list once. Nevertheless it's still O(N) time complexity and O(1) space complexity, while the recursive solution is O(N) for both (time and space).
    – gliderkite
    Nov 11 at 14:00

















up vote
0
down vote



accepted










This is how you could write the method without using recursion.



fn remove_nth(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let get_length = |l: &Link| {
let mut length = 0;
let mut current = l;
while let Some(n) = {current} {
length += 1;
current = &n.next;
}
length
};
let length = get_length(list);
let mut i = 0;
let mut current = list;
while i < length - n {
if let Some(link) = {current} {
current = &mut link.next;
} else {
panic!("Invalid node!");
}
i += 1;
}
*current = current.as_mut().unwrap().next.take();
}


Unfortunately, I didn't manage to make the borrow checker happy by using the more efficient runner pattern.






share|improve this answer

















  • 1




    @Stargateur of course recursion is less efficient, since space complexity would be O(N) compared to the O(1) of the runner pattern.
    – gliderkite
    Nov 11 at 10:18






  • 1




    Every iterative function can be write in the form of tail recursive function, what you are saying is completely false. recursion can do this in O(1) like iterative can do this in O(1). Everything iterative can do recursive can and vice versa.
    – Stargateur
    Nov 11 at 11:20








  • 1




    @Stargateur If you were to rewrite this recursively, you'd have to write two recursive algorithms, because it contains two loops. My recursive solution traverses the list only once, but at the cost of O(n) space. So that is the comparison being made here, not recursion vs. iteration in general.
    – trentcl
    Nov 11 at 13:39










  • I think by "runner pattern" gliderkite means the algorithm OP was trying to use, i.e. two pointers that traverse the list n nodes apart. When the first pointer reaches the end, the second pointer is pointing at the node to be removed. But to be honest... I don't really see how this solution is more efficient than that. Perhaps I'm missing something.
    – trentcl
    Nov 11 at 13:41






  • 1




    Pheraps I didn't explain myself well. My solution is less efficient than the runner pattern the OP was trying to use, because it needs to iterate in the worst case twice the list (to get its length first), while using the runner pattern you only need to iterate the list once. Nevertheless it's still O(N) time complexity and O(1) space complexity, while the recursive solution is O(N) for both (time and space).
    – gliderkite
    Nov 11 at 14:00















up vote
0
down vote



accepted







up vote
0
down vote



accepted






This is how you could write the method without using recursion.



fn remove_nth(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let get_length = |l: &Link| {
let mut length = 0;
let mut current = l;
while let Some(n) = {current} {
length += 1;
current = &n.next;
}
length
};
let length = get_length(list);
let mut i = 0;
let mut current = list;
while i < length - n {
if let Some(link) = {current} {
current = &mut link.next;
} else {
panic!("Invalid node!");
}
i += 1;
}
*current = current.as_mut().unwrap().next.take();
}


Unfortunately, I didn't manage to make the borrow checker happy by using the more efficient runner pattern.






share|improve this answer












This is how you could write the method without using recursion.



fn remove_nth(list: &mut Link, n: usize) {
if list.is_none() {
return;
}
let get_length = |l: &Link| {
let mut length = 0;
let mut current = l;
while let Some(n) = {current} {
length += 1;
current = &n.next;
}
length
};
let length = get_length(list);
let mut i = 0;
let mut current = list;
while i < length - n {
if let Some(link) = {current} {
current = &mut link.next;
} else {
panic!("Invalid node!");
}
i += 1;
}
*current = current.as_mut().unwrap().next.take();
}


Unfortunately, I didn't manage to make the borrow checker happy by using the more efficient runner pattern.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 10 at 23:56









gliderkite

6,25752968




6,25752968








  • 1




    @Stargateur of course recursion is less efficient, since space complexity would be O(N) compared to the O(1) of the runner pattern.
    – gliderkite
    Nov 11 at 10:18






  • 1




    Every iterative function can be write in the form of tail recursive function, what you are saying is completely false. recursion can do this in O(1) like iterative can do this in O(1). Everything iterative can do recursive can and vice versa.
    – Stargateur
    Nov 11 at 11:20








  • 1




    @Stargateur If you were to rewrite this recursively, you'd have to write two recursive algorithms, because it contains two loops. My recursive solution traverses the list only once, but at the cost of O(n) space. So that is the comparison being made here, not recursion vs. iteration in general.
    – trentcl
    Nov 11 at 13:39










  • I think by "runner pattern" gliderkite means the algorithm OP was trying to use, i.e. two pointers that traverse the list n nodes apart. When the first pointer reaches the end, the second pointer is pointing at the node to be removed. But to be honest... I don't really see how this solution is more efficient than that. Perhaps I'm missing something.
    – trentcl
    Nov 11 at 13:41






  • 1




    Pheraps I didn't explain myself well. My solution is less efficient than the runner pattern the OP was trying to use, because it needs to iterate in the worst case twice the list (to get its length first), while using the runner pattern you only need to iterate the list once. Nevertheless it's still O(N) time complexity and O(1) space complexity, while the recursive solution is O(N) for both (time and space).
    – gliderkite
    Nov 11 at 14:00
















  • 1




    @Stargateur of course recursion is less efficient, since space complexity would be O(N) compared to the O(1) of the runner pattern.
    – gliderkite
    Nov 11 at 10:18






  • 1




    Every iterative function can be write in the form of tail recursive function, what you are saying is completely false. recursion can do this in O(1) like iterative can do this in O(1). Everything iterative can do recursive can and vice versa.
    – Stargateur
    Nov 11 at 11:20








  • 1




    @Stargateur If you were to rewrite this recursively, you'd have to write two recursive algorithms, because it contains two loops. My recursive solution traverses the list only once, but at the cost of O(n) space. So that is the comparison being made here, not recursion vs. iteration in general.
    – trentcl
    Nov 11 at 13:39










  • I think by "runner pattern" gliderkite means the algorithm OP was trying to use, i.e. two pointers that traverse the list n nodes apart. When the first pointer reaches the end, the second pointer is pointing at the node to be removed. But to be honest... I don't really see how this solution is more efficient than that. Perhaps I'm missing something.
    – trentcl
    Nov 11 at 13:41






  • 1




    Pheraps I didn't explain myself well. My solution is less efficient than the runner pattern the OP was trying to use, because it needs to iterate in the worst case twice the list (to get its length first), while using the runner pattern you only need to iterate the list once. Nevertheless it's still O(N) time complexity and O(1) space complexity, while the recursive solution is O(N) for both (time and space).
    – gliderkite
    Nov 11 at 14:00










1




1




@Stargateur of course recursion is less efficient, since space complexity would be O(N) compared to the O(1) of the runner pattern.
– gliderkite
Nov 11 at 10:18




@Stargateur of course recursion is less efficient, since space complexity would be O(N) compared to the O(1) of the runner pattern.
– gliderkite
Nov 11 at 10:18




1




1




Every iterative function can be write in the form of tail recursive function, what you are saying is completely false. recursion can do this in O(1) like iterative can do this in O(1). Everything iterative can do recursive can and vice versa.
– Stargateur
Nov 11 at 11:20






Every iterative function can be write in the form of tail recursive function, what you are saying is completely false. recursion can do this in O(1) like iterative can do this in O(1). Everything iterative can do recursive can and vice versa.
– Stargateur
Nov 11 at 11:20






1




1




@Stargateur If you were to rewrite this recursively, you'd have to write two recursive algorithms, because it contains two loops. My recursive solution traverses the list only once, but at the cost of O(n) space. So that is the comparison being made here, not recursion vs. iteration in general.
– trentcl
Nov 11 at 13:39




@Stargateur If you were to rewrite this recursively, you'd have to write two recursive algorithms, because it contains two loops. My recursive solution traverses the list only once, but at the cost of O(n) space. So that is the comparison being made here, not recursion vs. iteration in general.
– trentcl
Nov 11 at 13:39












I think by "runner pattern" gliderkite means the algorithm OP was trying to use, i.e. two pointers that traverse the list n nodes apart. When the first pointer reaches the end, the second pointer is pointing at the node to be removed. But to be honest... I don't really see how this solution is more efficient than that. Perhaps I'm missing something.
– trentcl
Nov 11 at 13:41




I think by "runner pattern" gliderkite means the algorithm OP was trying to use, i.e. two pointers that traverse the list n nodes apart. When the first pointer reaches the end, the second pointer is pointing at the node to be removed. But to be honest... I don't really see how this solution is more efficient than that. Perhaps I'm missing something.
– trentcl
Nov 11 at 13:41




1




1




Pheraps I didn't explain myself well. My solution is less efficient than the runner pattern the OP was trying to use, because it needs to iterate in the worst case twice the list (to get its length first), while using the runner pattern you only need to iterate the list once. Nevertheless it's still O(N) time complexity and O(1) space complexity, while the recursive solution is O(N) for both (time and space).
– gliderkite
Nov 11 at 14:00






Pheraps I didn't explain myself well. My solution is less efficient than the runner pattern the OP was trying to use, because it needs to iterate in the worst case twice the list (to get its length first), while using the runner pattern you only need to iterate the list once. Nevertheless it's still O(N) time complexity and O(1) space complexity, while the recursive solution is O(N) for both (time and space).
– gliderkite
Nov 11 at 14:00




















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242052%2fhow-to-remove-the-nth-node-from-the-end-of-a-linked-list%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Retrieve a Users Dashboard in Tumblr with R and TumblR. Oauth Issues