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

Posted

技术标签:

【中文标题】查找单链表的第 k 个到最后一个元素【英文标题】:Finding the kth to last element of a singly linked list 【发布时间】:2014-01-11 12:00:41 【问题描述】:

对于 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;

解决方案 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 值包装在一个类中并传递它。

我有两个问题:

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

    Java 中的Integer 类包装了int,但在第一个解决方案中将int 替换为Integer 效果不佳。为什么?

【问题讨论】:

在您的第一个解决方案中,我没有初始化 @Vorsprung 我相信“i”是一个方法参数,虽然我不知道初始调用是什么样的。 初始调用如下所示: 第一个解决方案: Node n = nthToLast(testRootNode , 2 , 0);第二种解决方案: Node n = nthToLast(testRootNode , 2 , new IntWrapper()); 你确定你的解决方案给你第k个到最后一个元素,而不是第k个元素吗? 【参考方案1】:

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

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

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

【讨论】:

它与可变/不可变无关,而是与 + 应用于盒装类型时的语义有关。 如果 IntWrapper “表现得像一个全局值”,是否可以只让 IntWrapper 成为一个全局变量?这样做有什么好处/坏处吗? 是的,您可以拥有一个全局的 IntWrapper 实例;在这种情况下,您不需要参数化它。从代码中的任何地方获取全局值真的很容易——这种容易转化为它们最大的缺点:很难推理它们的状态。毕竟,这取决于您是否选择将其视为劣势。例如 - 本质上是算法的问题域可能不会将此视为劣势,而业务建模 OO 解决方案可能会。【参考方案2】:

在您的解决方案 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); 

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于查找单链表的第 k 个到最后一个元素的主要内容,如果未能解决你的问题,请参考以下文章

[数据结构与算法] 链表的其他类型

如何找出单链表中的倒数第k个元素

单链表的节点数,合并,相交,反转

链式队列(Linked Queue)

试写出在不带头结点的单链表的第i个元素之前插入一个元素的算法 麻烦帮我修改下

4-4 链式表的按序号查找 (10分)