问题
I know that you can simply solve this question iteratively by using a counter to increment each time you pass a node in linkedlist; also creating an arraylist and setting the data found with each node inside it. Once you hit the tail of the linkedlist, just minus the Nth term from the total number of elements in the arraylist and you will be able to return the answer. However how would someone perform this using recursion? Is it possible and if so please show the code to show your genius :).
Note: I know you cannot return two values in Java (but in C/C++, you can play with pointers :])
Edit: This was a simple question I found online but I added the recursion piece to make it a challenge for myself which I've come to find out that it may be impossible with Java.
回答1:
Okay, I think think this should do the trick. This is in C++ but it should be easy to translate to Java. I also haven't tested.
Node *NToLastHelper(Node *behind, Node *current, int n) {
// If n is not yet 0, keep advancing the current node
// to get it n "ahead" of behind.
if (n != 0) {
return NToLastHelper(behind, current->next, n - 1);
}
// Since we now know current is n ahead of behind, if it is null
// the behind must be n from the end.
if (current->next == nullptr) {
return behind;
}
// Otherwise we need to keep going.
return NToLastHelper(behind->next, current->next, n);
}
Node *NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n);
}
edit: If you want to return the value of the last node, you can just change it to:
int NToLast(Node *node, int n) {
// Call the helper function from the head node.
return NToLastHelper(node, node, n)->val;
}
This code will fail badly if node is null.
回答2:
The trick is to do the work after the recursion. The array in the private method is basically used as a reference to a mutable integer.
class Node {
Node next;
int data;
public Node findNthFromLast(int n) {
return findNthFromLast(new int[] {n});
}
private Node findNthFromLast(int[] r) {
Node result = next == null ? null : next.findNthFromLast(r);
return r[0]-- == 0 ? this : result;
}
}
回答3:
As a general rule, anything that can be done with loops can also be done with recursion in any reasonable language. The elegance of the solution may be wildly different. Here is a fairly java idiomatic version. I've omitted the usual accessor functions for brevity.
The idea here is to recur to the end of the list and increment a counter as the recursion unwinds. When the counter reaches the desire value, return that node. Otherwise return null. The non-null value is just returned all the way tot the top. Once down the list, once up. Minimal arguments. No disrespect to Adam intended, but I think this is rather simpler.
NB: OP's statement about Java being able to return only one value is true, but since that value can be any object, you can return an object with fields or array elements as you choose. That wasn't needed here, however.
public class Test {
public void run() {
Node node = null;
// Build a list of 10 nodes. The last is #1
for (int i = 1; i <= 10; i++) {
node = new Node(i, node);
}
// Print from 1st last to 10th last.
for (int i = 1; i <= 10; i++) {
System.out.println(i + "th last node=" + node.nThFromLast(i).data);
}
}
public static void main(String[] args) {
new Test().run();
}
}
class Node {
int data; // Node data
Node next; // Next node or null if this is last
Node(int data, Node next) {
this.data = data;
this.next = next;
}
// A context for finding nth last list element.
private static class NthLastFinder {
int n, fromLast = 1;
NthLastFinder(int n) {
this.n = n;
}
Node find(Node node) {
if (node.next != null) {
Node rtn = find(node.next);
if (rtn != null) {
return rtn;
}
fromLast++;
}
return fromLast == n ? node : null;
}
}
Node nThFromLast(int n) {
return new NthLastFinder(n).find(this);
}
}
回答4:
The recursion function:
int n_to_end(Node *no, int n, Node **res)
{
if(no->next == NULL)
{
if(n==0)
*res = no;
return 0;
}
else
{
int tmp = 1 + n_to_end(no->next, n, res);
if(tmp == n)
*res = no;
return tmp;
}
}
The wrapper function:
Node *n_end(Node *no, int n)
{
Node *res;
res = NULL;
int m = n_to_end(no, n, &res);
if(m < n)
{
printf("max possible n should be smaller than or equal to: %d\n", m);
}
return res;
}
The calling function:
int main()
{
List list;
list.append(3);
list.append(5);
list.append(2);
list.append(2);
list.append(1);
list.append(1);
list.append(2);
list.append(2);
Node * nth = n_end(list.head, 6);
if(nth!=NULL)
printf("value is: %d\n", nth->val);
}
This code has been tested with different inputs. Although it's a C++ version, you should be able to figure out the logic :)
来源:https://stackoverflow.com/questions/16258402/is-it-possible-to-implement-an-algorithm-to-find-the-nth-to-last-element-of-a-si