【问题标题】:node delete: terminator node in a singly linked list?节点删除:单链表中的终止节点?
【发布时间】:2016-06-02 16:03:48
【问题描述】:

我有一个删除当前节点的实现。条件是:我们只知道当前节点。

这样做的方法是:

  • 将下一个节点的数据复制到当前节点中
  • 然后删除下一个节点

如下实现:

public class ListNode<T> {

  private ListNode<T> next = null;
  private T data;

  public ListNode(T data) {
    this.data = data;
  }

  /*
   * Add a new node after the current node
   * Time Complexity: O(1)
   */
  public void add(T data) {
    ListNode<T> newNode = new ListNode<T>(data);
    newNode.setNext(this.getNext());
    this.setNext(newNode);
  }

  /*
   * Delete the current node
   * Time Complexity: O(1)
   */
  public T delete() {
    ListNode<T> nextNode = next;
    if (nextNode == null) { /* The current node is the last node. */
      return null;
    }

    T nextData = nextNode.getData();
    this.setData(nextData);
    this.setNext(nextNode.getNext());
    return nextData;
  }

  /* getters and setters */

}

但是,有一个例外:如果当前节点是列表中的最后一个节点,这将不起作用。

我可以想办法解决这个问题:

  • 有一个特殊的节点TerminatorNode,它总是在链表的末尾。

我想知道:如何实现?或者,class这种节点应该是什么?

编辑 1: 为了清楚起见,我的问题是:我怎样才能始终删除当前节点,即使它是链表上的最后一个节点?我想要一个TerminalNode,它总是在链表的末尾,它只代表链表的末尾。 (类似于字符串末尾的\0。)然后其他正常节点总是可以使用相同的方法删除,时间为O(1)。

编辑 2: 这是关于破解编码面试的一些声明:

例如,您可以考虑将节点标记为虚拟节点。

这是什么意思?

【问题讨论】:

  • 如果你可以访问下一个节点的数据,这意味着你也有对下一个节点的引用。为什么不能简单地检查下一个节点是否为空?
  • 我的问题是:我怎样才能总是删除当前节点,即使它是链表上的最后一个节点?我想要一个TerminalNode,它总是在链表的末尾,它只代表链表的末尾。然后其他正常节点总是可以使用相同的方法删除,时间为 O(1)。
  • 这不是一个好主意。为什么会有冗余数据?您已经在“下一个”中有“空”。您只需要更好地处理 nextNode 为空。通过添加终结器,您什么也解决不了。
  • 我可以在 O(1) 时间内删除我可以访问的任何“当前节点”,即使它是列表中的最后一个节点。这实际上是我得到的一个面试问题,当时我被告知的答案是有这样一个特殊的“结束节点”。
  • 缺少很多信息:删除单个元素列表中的最后一个元素的预期结果是什么?您是否有一个包含对第一个元素的引用的 List&lt;T&gt; 类型?此列表的使用代码如何?您是否在某处引用了ListNode&lt;T&gt; 以引用其数据?如果这是一个面试问题,也许他们对你的方法更感兴趣,你对问题的分析......

标签: java list data-structures linked-list


【解决方案1】:

为简单起见,我们将终端节点表示为LinkedNode,将datanext 表示为null。我们还假设终端节点是结束列表的唯一有效方式。

private boolean isTerminalNode() {
    return this.getData() == null && this.getNext() == null;
}

如果列表的末尾始终是终端节点,则可以删除除终端之外的任何节点。

/*
 * Delete the current node Time Complexity: O(1)
 */
public T delete() {
    if (this.isTerminalNode()) {
        // Cannot delete the terminal node.
        // Either throw an IllegalArgumentException or return silently
        return null;
    }

    ListNode<T> nextNode = this.getNext();
    this.setData(nextNode.getData());
    this.setNext(nextNode.getNext());
    return this.getData();
}

但是,现在我们在节点之后添加时可能会遇到类似的问题。

/*
 * Add a new node after the current node Time Complexity: O(1)
 */
public void add(T data) {
    if (this.isTerminalNode()) {
        // Cannot add a node after the terminal node.
        // Either throw an IllegalArgumentException, return silently, or add
        // the data at the current position and create a new terminal node.
        throw new IllegalArgumentException("Cannot add a node after the terminal node");
    }

    ListNode<T> newNode = new ListNode<T>(data);
    newNode.setNext(this.getNext());
    this.setNext(newNode);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多