找到单个链表的最后一个元素的第k个

时间:2013-12-23 09:33:32

标签: java recursion pass-by-reference pass-by-value singly-linked-list

我有两个递归解决方案来解决Java中“单链表的最后一个元素”问题:

解决方案1:

public static Node nthToLast(Node head, int k , int i){
    if (head == null) return null;
    Node n = nthToLast(head.next, k, i);
    i = i + 1;

    if (i == k) return head;

    return n;
}

解决方案2:

public class IntWrapper {
    public int value = 0;
}
public static Node nthToLast(Node head, int k, IntWrapper i){
    if (head == null) return null;
    Node n = nthToLast(head.next, k, i);
    i.value = i.value + 1;

    if (i.value == k) return head;

    return n;
}

第一个解决方案返回null,而第二个解决方案完美无缺。第一个解决方案按值传递k,而第二个解决方案将int值包装在一个类中并传递它。

我有两个问题:

  1. 为什么第一个解决方案不能用于Java?为什么在每个方法调用中通过局部变量i的值传递与传递引用版本的工作方式不同?

  2. Java中的Integer类包装int,但在第一个解决方案中将int替换为Integer也不起作用。为什么呢?

3 个答案:

答案 0 :(得分:1)

1。 第一个解决方案不起作用,因为每次在i变量中传递相同的值。如果您将行i = i + ​​1移到第Node n = nthToLast (head.next, k, i)行,那么一切都应该没有问题 2。 Integer类是不可变的,因此行为类似于普通int。这就是为什么如果你在第一个解决方案函数中使用Integer将无法正常工作。如上所述,您可以替换第一个解决方案与Integer一起使用的代码行 第二种解决方案有效,因为递增计数器的方式不会覆盖对计数对象的引用。

答案 1 :(得分:0)

在解决方案2中,您使用IntWrapper来记住递归调用中的值。在这里,IntWrapper就像一个全球价值。

如果使用诸如基本整数之类的局部变量,则无法在调用之间保留递增的(i = i + 1)值。因此,语句if (i == k) return head;永远不会成立,除非k = 1。

最有趣的是,您不能使用Integer,因为Java包装类本质上是不可变的。你做i = i + 1的那一刻,就会创建一个新对象(LHS),抛弃旧对象(RHS)/垃圾回收。

答案 2 :(得分:0)

在你的解决方案1中,你应该在递归调用方法之前增加i。这个版本应该有效:

public static Node nthToLast(Node head, int k , int i) {
    // checks empty case
    if (head == null) { return null; }

     // checks if current node is the solution
    if (i == k) { return head; }

    // else checks next node
    return nthToLast(head.next, k, i+1); 
}