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

Java 查找单链表最后一个元素的第k个,java,recursion,pass-by-reference,pass-by-value,singly-linked-list,Java,Recursion,Pass By Reference,Pass By Value,Singly Linked List,对于Java中的“单链表的第k个到最后一个元素”问题,我有两个递归解决方案: 解决方案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; } public cl

对于Java中的“单链表的第k个到最后一个元素”问题,我有两个递归解决方案:

解决方案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;
}
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;
}
解决方案2:

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;
}
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
值包装在一个类中并传递它

我有两个问题:

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

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


  • 在解决方案2中,您使用
    IntWrapper
    在递归调用中记住值。在这里,
    IntWrapper
    的作用类似于一个全局值

    如果使用基本整数等局部变量,则无法在调用过程中保留递增(
    i=i+1
    )值。因此,语句
    if(i==k)返回head永远不会变为真,除非k=1


    最有趣的是,您不能使用
    Integer
    ,因为Java包装器类本质上是不可变的。当您执行
    i=i+1
    时,将创建一个新对象(LHS),旧对象(RHS)将被丢弃/垃圾回收。

    在解决方案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); 
    }
    
    一,。 第一个解决方案不起作用,因为每次在
    i
    变量中传递相同的值时。如果移动行
    i=i+​​1
    在线路上
    节点n=nthToLast(head.next,k,i)
    ,一切都应该正常工作。
    2.
    Integer
    类是不可变的,因此其行为类似于正常的
    int
    。这就是为什么如果在第一个解函数中使用
    整数
    ,将无法正常工作。您可以替换前面提到的代码行,第一个解决方案使用的是
    整数


    第二种解决方案有效,因为您递增计数器的方式不会覆盖对计数对象的引用。

    在第一种解决方案中,我不是initialized@Vorsprung我相信“我”是一个方法论,虽然我不知道初始调用是什么样子,但初始调用如下所示:第一个解决方案:Node n=nthToLast(testRootNode,2,0);第二种解决方案:Node n=nthToLast(testRootNode,2,newintwrapper());您确定您的解决方案为您提供了最后一个元素的第k个,而不是第一个元素的第k个?这与可变/不可变无关,而是与应用于装箱类型时的
    +
    语义有关。如果IntWrapper“像全局值一样工作”,是否可以将IntWrapper改为全局变量?这样做有什么优点/缺点吗?是的,您可以有一个全局的IntWrapper实例;在这种情况下,不需要对其进行参数化。从代码中的任何地方获得全局值都是非常容易的——这种容易转化为它们最大的缺点:很难对它们的状态进行推理。正如所有事情一样,这取决于你是否选择把它作为一个劣势。例如,一个本质上是算法的问题域可能不认为这是一个缺点,而业务建模的OO解决方案可能。