繁体   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

我知道您可以通过使用计数器在每次通过链表中的节点时递增来简单地迭代解决这个问题; 还创建一个数组列表并设置在其中的每个节点找到的数据。 一旦您找到链表的尾部,只需从数组列表中的元素总数中减去第 N 项,您就可以返回答案。 但是,有人如何使用递归来执行此操作? 是否有可能,如果有,请显示代码以显示您的天才:)。

注意:我知道你不能在 Java 中返回两个值(但在 C/C++ 中,你可以使用指针:])

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

诀窍是在递归之后做这项工作。 私有方法中的数组基本上用作对可变整数的引用。

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

作为一般规则,任何可以用循环完成的事情也可以用任何合理语言的递归完成。 解决方案的优雅可能大不相同。 这是一个相当java惯用的版本。 为简洁起见,我省略了常用的访问器函数。

这里的想法是递归到列表的末尾并在递归展开时增加一个计数器。 当计数器达到期望值时,返回该节点。 否则返回空值。 非空值一直返回到顶部。 一次下降,一次上升。 最少的争论。 无意不尊重亚当,但我认为这更简单。

注意:OP 关于 Java 只能返回一个值的声明是正确的,但由于该值可以是任何对象,因此您可以根据需要返回带有字段或数组元素的对象。 然而,这里不需要。

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

好的,我认为这应该可以解决问题。 这是在C++但它应该很容易转换为Java 我也没有测试。

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

编辑:如果要返回最后一个节点的值,只需将其更改为:

int NToLast(Node *node, int n) {
  // Call the helper function from the head node.
  return NToLastHelper(node, node, n)->val;
}

如果 node 为空,此代码将严重失败。

递归函数:

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

包装函数:

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

调用函数:

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

此代码已使用不同的输入进行了测试。 虽然它是 C++ 版本,但您应该能够弄清楚逻辑:)

暂无
暂无

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

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