微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java.util.List上的get0始终是O1吗?

如何解决java.util.List上的get0始终是O1吗?

据我所知,有以下实现:

  • ArrayList
  • LinkedList
  • 向量
  • 堆栈

(基于http://tutorials.jenkov.com/java-collections/list.html,如果有错,请正确)

ArrayList是一个动态数组实现,因此,与数组一样,get为O(1),LinkedList的Head为O(1),Vector和Stack基于ArrayList,因此为O(1)。>

因此,在每种情况下,如果O(1)都是List的,则在任何内置的get(0)上执行(因为您可以自己创建O(n!)的get(0)TS,以实现特定目的) ?

解决方法

java.util.List上的get(0)总是O(1)吗?

让我们假设有一个参数N代表列表的长度 1

对于您提到的List的4种实现,get(0)的确是O(1)的操作:

  • ArrayListVectorStack都使用数组下标实现get(i),这是一个O(1)操作。

  • LinkedList.get(i)涉及i的{​​{1}}链接遍历。但是,如果O(i)是一个常数,则可以简化为i

不过,O(1)还有其他“内置”实现。的确,如果包括各种非公开的实现,例如有实现子列表,不可修改的列表等的List类,那么它们的数量就很多。从这4个概括为“所有人”听起来不是 2


但是对于List的所有可能实现,get(0)不会是O(1)

  • 考虑一个简单的链表,其中的元素以相反的顺序链接。由于List需要遍历列表的末尾,因此get(0)链接遍历为:N

  • 考虑一个第一次从数据库查询结果集中的行中完全填充了 的列表。第一个O(N)调用将至少是get,因为您要获取O(N)行。 (如果数据库查询不是N,可能比O(N)还要糟糕。)因此,对 }或更糟。

实际上,有些匠心独具的人可以发明一种自定义列表,其中O(N)具有您想提出的任何Big-O复杂性。


1-我在这里故意含糊。一方面,我们需要标识一个变量get来表示“问题”的大小,以便进行复杂性分析。 (列表的长度是显而易见的选择。)另一方面,当您考虑实现接口的所有可能方式时,O(N)的长度是一个令人惊讶的“累赘”概念。

2-我假设您是在问这个问题,因为您想编写一些依赖于get(0)N的库代码。由于您无法阻止某人通过非内置列表实现使用您的库,因此即使我们可以检查所有可能的情况(过去,当前或将来),您对“假设它是内置的”约束也无济于事。未来)为您内置的List实现。

,

忽略自定义实现,仅查看内置实现(如问题末尾所建议的那样),无论如何,您仍然不能说get(0)将是 O(1)列表大小。

例如,在基于get(0)的子列表上调用LinkedList将是 O(n)

List<Integer> list = new LinkedList<>(Arrays.asList(1,2,3,4,5,6,7,8,9));
List<Integer> subList = list.subList(4,8);
Integer num = subList.get(0); // <===== O(n),not O(1)

在该代码中,subList.get(0)内部调用list.get(4),时间复杂度为O(n)。

,

是的,对于您提到的List的所有实现,get(0)是O(1)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。