简体   繁体   English

是否可以实现一种算法来使用java中的递归查找单向链表的第n个到最后一个元素

[英]Is it possible to implement an algorithm to find the nth to last element of a singly linked list using recursion in java

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.一旦您找到链表的尾部,只需从数组列表中的元素总数中减去第 N 项,您就可以返回答案。 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 :])注意:我知道你不能在 Java 中返回两个值(但在 C/C++ 中,你可以使用指针:])

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.编辑:这是我在网上找到的一个简单问题,但我添加了递归部分以使其成为对自己的挑战,我发现这可能无法使用 Java。

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;  
  }
}

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.这是一个相当java惯用的版本。 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.注意:OP 关于 Java 只能返回一个值的声明是正确的,但由于该值可以是任何对象,因此您可以根据需要返回带有字段或数组元素的对象。 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);
    }
}

Okay, I think think this should do the trick.好的,我认为这应该可以解决问题。 This is in C++ but it should be easy to translate to Java .这是在C++但它应该很容易转换为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.如果 node 为空,此代码将严重失败。

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 :)虽然它是 C++ 版本,但您应该能够弄清楚逻辑:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM