【问题标题】:Reversing LinkedList in Java在 Java 中反转 LinkedList
【发布时间】:2011-05-02 20:38:19
【问题描述】:

我正在查看这篇帖子中的解决方案Reversing a linked list in Java, recursively

我复制了以下解决方案之一。我已经实现了,效果很好。

public ListNode Reverse(ListNode list)
{
    if (list == null) return null; // first question

    if (list.next == null) return list; // second question

    // third question - in Lisp this is easy, but we don't have cons
    // so we grab the second element (which will be the last after we reverse it)

    ListNode secondElem = list.next;

    // bug fix - need to unlink list from the rest or you will get a cycle
    list.next = null;

    // then we reverse everything from the second element on
    ListNode reverseRest = Reverse(secondElem);

    // then we join the two lists
    secondElem.Next = list;

    return reverseRest;
}

然而,我不明白的是最后几行。

secondElem.next = list;
return reverseRest;

看来我们根本没有返回 secondElem?但是我通过代码进行了调试,看起来 secondElem 已经在 reverseRest 中。这是因为它是 Java 中的值引用,并且在应用 secondElem.Next=list 时会自动更新?

【问题讨论】:

    标签: java collections


    【解决方案1】:

    然而,我不明白的是最后几行。

    secondElem.next = 列表;
    返回反向休息;

    让我一一解释你没看懂的2行:

    1.secondElem.next = list;
    

    我认为 secondElem 的创建引入了额外的复杂性。变量 secondElem 根本不需要。

    而不是这个:

        // then we reverse everything from the second element on
        ListNode reverseRest = Reverse(secondElem);
    
        // then we join the two lists
        secondElem.Next = list;
    

    使用这个:

    ListNode reverseRest = Reverse(list.next);    
    list.next.next = list;
    

    更容易掌握。最后一行代码清楚地展示了列表反转过程本身!

    2. return reverseRest;
    

    查看 reverseRest 变量的用法并了解其用途。它的唯一目的是将列表的原始尾部的值渗透到所有递归调用的末尾,以便我们可以将原始尾部(也是新的头部)返回给调用 Reverse 函数的主函数。您必须通过了解我们根本没有在递归调用之间更改变量 reverseRest 的值来快速了解这一点 - 无论我们从 Reverse(secondElem) 收到什么作为返回值,我们都会从函数中“按原样”返回它!

    【讨论】:

      【解决方案2】:

      不要考虑传递语义,要考虑内存中的对象和包含对它们的引用的变量。

      初始状态:

      (list)
         |
         V
      [  1  ] -> [  2  ] -> ... -> [  N  ]
      

      list.next = null;之后:

      (list)   (secondElem)
         |          |
         V          V
      [  1  ]    [  2  ] -> ... -> [  N  ]
      

      递归调用后:

      (list)   (secondElem)      (reverseRest)
         |          |                 |
         V          V                 V
      [  1  ]    [  2  ] <- ... <- [  N  ]
      

      secondElem.Next = list;之后的最终状态:

      (list)   (secondElem)      (reverseRest)
         |          |                 |
         V          V                 V
      [  1  ] <- [  2  ] <- ... <- [  N  ]
      

      【讨论】:

        【解决方案3】:

        如果您的目标是简单地反转列表,请使用Collections.reverse(list)

        【讨论】:

        • 更好的是,使用descendingIterator()
        • 这取决于他是想“永远”反转列表,还是只想以相反的顺序迭代它。
        猜你喜欢
        • 1970-01-01
        • 2016-07-05
        • 1970-01-01
        • 1970-01-01
        • 2019-11-22
        • 2013-04-06
        • 1970-01-01
        • 2013-08-01
        • 2018-02-25
        相关资源
        最近更新 更多