【问题标题】:List implementation清单实施
【发布时间】:2013-01-15 18:35:52
【问题描述】:

假设有一个数字列表——存储在数组、队列、链表或任何支持列表数据结构的东西中(即数字序列很重要)。现在,假设我们想在将一个数字添加到现有列表后添加一个新对象(list.add())。但是, list.add() 接受原始列表并返回一个新列表,其中包含原始列表中的数字和新数字。函数 add() 不会以任何方式更改原始列表对象。

所以,要实现这个一种方法是,我们在函数中复制原始列表,将新数字添加到其中,然后将其返回。这需要 O(n) 时间。

那么有没有其他方法可以让我们在比 O(n) 更短的时间内完成这项工作。

编辑 1: 该元素将在最后添加。 add() 返回的对象应该包含原始列表中的所有数字和新的数字。原始列表保持不变。

编辑 2: 我认为,如果我们每次向列表中添加数字时不复制整个列表,这可能是可能的。这方面有没有可能?

【问题讨论】:

  • 你在哪里添加新节点?到头部,尾部,中间?
  • @Oli Charlesworth...到最后

标签: data-structures complexity-theory time-complexity


【解决方案1】:

附加到链表的头部将是 O(1)。

另外,支持随机插入是最近大量研究的主题。 Clojure 和 Scala 使用类似于 Hash array mapped trie 的东西,除了一个不可变的变体,它允许通过仅复制受 O(logn) 中的更新影响的分支来更快地更新。当分支因子很高(即 32)时,这也允许有效地进行持续查找。

【讨论】:

  • @dicarlo2...插入在最后...您能否说明您的答案...我希望返回的对象包含原始列表中的所有节点以及新的数字.原始对象不会被返回,也不会被函数改变。
【解决方案2】:

为什么要复制?

您可以在 O(1) 中添加到列表或数组的末尾

基本上只是在后面加上数字并使用相同的参数并将大小增加 1,然后创建一个列表对象,这就是 O(1)

【讨论】:

  • 这与某些编程风格和关注点有关,通常使对象不可变。这通常是为了使处理多线程或并发代码更安全、更容易。并且将元素添加到列表/数组的“尾”端不是必要 O(1),这将取决于实现(例如,链表通常是 O(n))
  • 是的,否则 BST 将是对数的,你是对的。这是否也涉及释放先前的对象?并发代码如何更安全?
  • 假设您有一个项目列表和两个线程/进程 - 一个记录所有项目,另一个将项目按顺序排列。如果不小心,项目可能会被记录不止一次,或者根本不记录。同步访问将不起作用,因为它最终会消除线程实现的好处。因此,记录器应该在列表的副本上工作(假设顺序不重要)。某些语言/平台可能有特殊的实现,使复制比 O(n) 操作(迭代复制)更有效,这是日志记录所需要的。
【解决方案3】:

不确定您需要支持哪些其他类型的功能,但如果 add 是您关心的唯一方法,您可以创建一个包装类,该类基本上维护一个新列表,该列表代表您添加到原始清单。然后,将lookup 放入此包装类时会考虑原始列表和新列表的连接。

这是一些示例伪 C# 代码:

public class ListWrapper
{
    private ArrayList<T> Original;
    private ArrayList<T> ConcatenatedPortion;

    public ImmutableList(ArrayList<T> original)
    {
        Original = original;
        ConcatenatedPortion = new ArrayList<T>();
    }

    public bool Add(<T> element)
    {
        return ConcatenpatedPortion.Add(element);
    }

    public <T> Get(int index)
    {
        if (index < 0) throw new IndexOutOfBoundsException();

        if (index < Original.Length)
            return Original.Get(index);

        int newIndex = index - Original.Length;

        if (newIndex < ConcatenatedPortion.Length)
            return ConcatenatedPortion.Get(newIndex);

        throw new IndexOutOfBoundsException();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 1970-01-01
    • 2012-12-02
    • 1970-01-01
    相关资源
    最近更新 更多