【问题标题】:Remove Minimum Element from a Java Linked List从 Java 链表中删除最小元素
【发布时间】:2017-03-27 13:29:58
【问题描述】:

我正在尝试从 Java LinkedList 中删除一个最小元素。

为了找到最小值,我必须遍历一次 LinkedList。我想保存该元素的节点或迭代器以在 O(1) 中将其删除。

正常

list.remove(Object o)

需要 O(n) 步。

void removeMin(LinkedList<Integer> list) {
    ListIterator<Integer> itList = list.listIterator();

    Integer min = itList.next();

    while(itList.hasNext()) {
        Integer curVal = itList.next();
        if(curVal < min) {
            min = curVal 
            // Copy the iterator here?
        }        
    }
    // remove min from list here.
}

有没有办法在找到新的最小值时复制迭代器,以便之后调用迭代器的 remove()?

【问题讨论】:

  • 备注:你必须在你的List中使用'Integer',而不是原始类型'int'
  • 你说得对,我改变了我的示例代码......仍然存在问题,但我从 glee8e 的评论链接中读到的内容,似乎不可能-.-
  • 你为什么要这样做?您希望提高性能吗?
  • 如您所说,您必须至少遍历您的列表一次。那已经是O(n)。如果你遍历它两次(第一次找到最小元素,第二次删除它)整体复​​杂度仍然是O(n)

标签: java data-structures


【解决方案1】:

您可以通过这种方式复制当前.next索引处的迭代器:

ListIterator<Integer> minItList = List.listIterator(itList.nextIndex());

解决方案如下:

ListIterator<Integer> itList = list.listIterator();
ListIterator<Integer> minItList = list.listIterator();

Integer min = itList.next();

while(itList.hasNext()) {
    Integer curVal = itList.next();
    if(curVal < min) {
        min = curVal; 
        // Copy the iterator here?
        minItList = list.listIterator(itList.nextIndex());
    }        
}
  // remove min from list here.
  minItList.previous();  
  minItList.remove();  //note that you can't call .remove() on list iterator until .next() or .previous() have been called once because you will get IllegalStateException

【讨论】:

  • 是的,但它需要 O(n)。只是猜测这可能是提问者想要避免的。
  • 你是对的,但我认为这是实现他想要的唯一可能的方法。
  • 我同意。
  • 不错的想法,但它不起作用,抱歉。首先,每次达到初步最小值时,都会创建一个列表迭代器,最坏的情况是 n 次,通常可能只是 squareroot(n)。接下来,创建列表迭代器是 O(n),因为它必须逐步遍历列表到所需位置。因此,仅这一切就是 O(n*n) 或 O(n^2)。之后你是对的,调用remove() 是 O(1)。
  • 感谢@MohammadOghli 邀请我重新参与讨论。这不是关于语言,而是关于java.util.LinkedList 的设计。在 Java 中设计一个链表很容易,它允许您访问链表的节点,以便您可以保存对要删除的节点的引用。然后你可以在 O(1) 中删除。它会“只是”打破封装原则。
【解决方案2】:

我不知道它是否更快,但你可以使用Collections.min(...)

void removeMin(LinkedList<Integer> list) {
    list.remove(Collections.min(list));
}

【讨论】:

    【解决方案3】:

    无论如何,如果你使用顺序搜索符号表(无序列表),在最坏的情况下,对于 removeOperation,最小元素的查找将是 O(N) + O(M),其中 M 是 Min Node 的“位置”。 可能你应该使用二进制搜索符号表(有序),其中头部存储最小值,你用 O(1) 时间可以删除最小值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-08
      • 2020-10-29
      • 2014-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-09
      相关资源
      最近更新 更多