在Cracking the Coding Interview(第6版)一书中,一个问题要求我:
实现算法以查找单链表的最后一个元素
后来,作者声称:
不幸的是,我们无法使用正常的return语句传回一个节点和一个计数器。
她在上面的语句中引用了Java语言。她后来证明我们只能在Java中打印单链表中的第k个元素。
我的问题是:当递归弹出帧时,为什么我们不能传回一个节点?为什么我们不能在递归函数中添加另一个参数,以便将该参数设置在我们正在寻找的节点的正确时间(即当index =第k项时)?我从昨晚开始就一直在考虑这个问题,而我却无法绕过它。
提供的示例答案如下所示:
int printKthToLast (LinkedListNode head, int k) {
if(head == null) {
return 0;
}
int index = printKthToLast(head.next, k) + 1;
if (index == k) {
System.out.println(k + "th to last node is " + head.data);
}
return index;
}
答案 0 :(得分:3)
当你说我们可以"在递归函数中添加另一个参数以便在正确的时间设置参数时,你是对的"。例如,此功能的工作方式与您发布的解决方案相同:
private void printKthToLast(LinkedListNode head, int k, int index) {
if(head == null) {
return;
}
if(index >= k) {
System.out.println(head.data);
}
printKthToLast(head.next, k, ++index);
}
我的猜测是,作者试图说明递归通常" 将问题划分为子问题,解决这些子问题,结合结果强>" (即经典的分而治之方法)。在这种情况下,当我们在" next"上调用递归函数时,将问题划分为子问题。因为我们越接近基本情况(head == null)。要合并的结果是索引,必须递归递增以确定何时必须打印节点。这就是索引建立函数返回类型(int)的原因。这是递归地解决问题的正确方法。你建议的是一种可能性,但通过" index"作为参数既不是将问题划分为子问题也不是将结果组合。
此外,考虑到在Java中,方法不仅可以通过它们的名称来识别,还可以通过它们的输入参数,返回类型等来识别。因此,这两种方法......
private int printKthToLast(LinkedListNode head, int k)
private void printKthToLast(LinkedListNode head, int k, int index)
...完全不同,即使它们具有相同的名称(这称为多态)。因此,在同一解决方案中包含这两种方法不会是递归。
答案 1 :(得分:0)
LinkedListNode
由LinkedList
内部使用。
LinkedList
上没有允许检索内部LinkedListNode
(实际上称为Entry
)的公开方法。
因此,给定LinkedList
,您无法访问内部节点。
然而,如果只是通过列表,你可以简单地使用迭代器并递归它:
int printKthToLast (Iterator<E> it, int i) {
if(!it.hasNext()) {
return 0;
}
E e = it.next();
// ...
}