[英]Finding the kth to last element of a singly linked list
I have two recursive solutions to the "kth to last element of a singly linked list" problem in Java: 对于Java中的“单链列表的第k个元素”,我有两种递归解决方案:
Solution 1: 解决方案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;
}
Solution 2: 解决方案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;
}
The first solution returns null
, while the second solution works perfectly. 第一个解决方案返回
null
,而第二个解决方案完美运行。 The first solution passes k
by value, while the second solution wraps the int
value in a class and passes it. 第一个解决方案按值传递
k
,而第二个解决方案将int
值包装在一个类中并传递它。
I have two questions: 我有两个问题:
Why is the first solution not working in Java? 为什么第一个解决方案在Java中不起作用? Why is pass-by-value through the local variable
i
in each method call not working the same as the pass-by-reference version? 为什么在每个方法调用中通过局部变量
i
的值传递与传递引用版本不同?
The Integer
class in Java wraps int
, but replacing the int
to Integer
in the first solution does not work as well. Java中的
Integer
类包装了int
,但是在第一个解决方案中将int
替换为Integer
并不能正常工作。 Why? 为什么?
1. The first solution does not work because every time you pass the same value in a i
variable. 1.第一种解决方案不起作用,因为每次您在
i
变量中传递相同的值。 If you move the line i = i + 1
over the line Node n = nthToLast (head.next, k, i)
, everything should work without a problem. 如果将行
i = i + 1
移到行Node n = nthToLast (head.next, k, i)
,则一切都应该正常工作。
2. Integer
class is immutable, so behaves like a normal int
. 2.
Integer
类是不可变的,因此其行为类似于普通的int
。 That's why if you use an Integer
in the first solution function will not work correctly. 这就是为什么如果在第一个解决方案中使用
Integer
函数将无法正常工作的原因。 You can replace lines of code as I mentioned above that the first solution worked with an Integer
. 您可以替换上面我提到的第一个解决方案与
Integer
一起使用的代码行。
The second solution works because the way you increment the counter does not overwrite the reference to the counting object. 第二种解决方案之所以有效,是因为您增加计数器的方式不会覆盖对计数对象的引用。
In Solution 2, you're using IntWrapper
to remember values across recursive invocations. 在解决方案2中,您正在使用
IntWrapper
记住跨递归调用的值。 Here, IntWrapper
acts like a global value. 在这里,
IntWrapper
作用就像一个全局值。
If you use local variables such as a primitive integer, you cannot preserve the incremented ( i = i + 1
) values across invocations. 如果使用局部变量(例如原始整数),则无法在调用之间保留递增的(
i = i + 1
)值。 Therefore, the statement if (i == k) return head;
因此,语句
if (i == k) return head;
never becomes true, unless maybe if k = 1. 除非k = 1。
Most interestingly, you cannot use Integer
because Java wrapper classes are immutable in nature. 最有趣的是,您不能使用
Integer
因为Java包装器类本质上是不可变的。 The moment you do i = i + 1
, a new object is created (LHS) and the old one (RHS) is thrown away/garbage collected. 当您执行
i = i + 1
的那一刻,将创建一个新对象(LHS),而一个旧对象(RHS)将被丢弃/收集垃圾。
In your solution 1 you should increment i before calling recursively the method. 在您的解决方案1中,您应在递归调用该方法之前使i递增。 This version should work:
这个版本应该工作:
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.