任何集合 O(1) 的索引时间复杂度吗?

huangapple go评论67阅读模式
英文:

Any collection O(1) indexOf time complexity?

问题

有没有人可以帮助我弄清楚,是否在Java(或任何语言通用的语言)中有一种集合类型提供indexOf(Item item)操作的O(1)时间复杂度?[您可以假设没有重复项,或者仅返回第一个索引]

如果没有,有人可以帮助我推断为什么没有形成这样的东西吗?有什么特殊的原因吗?

英文:

Can anyone help me to figure out that, is there any collection type in java (or any language agonistic one) that offers O(1) time complexity for indexOf(Item item) operation? [You may assume there are no duplicates or simply the first index to be returned]

If there is nothing, can anyone help me out to deduct the reason why such has not been formed? Any particular reason?

答案1

得分: 3

没有Java(标准)集合类型具有该属性。

indexOf(Object) 方法在 List 中声明,没有 List 实现提供比 O(N) 更好的查找效率。

还有其他集合类型提供 O(logN)O(1) 的查找效率,但它们不像 indexOf(Object) 那样返回一个位置(和索引)。(HashMapHashSet 分别提供 O(1)get(key)contains(object)。)

> 如果没有,是否有人可以帮助我推断为什么没有形成这样的原因?有什么特殊的原因吗?

因为一个提供此功能的数据结构将会变得复杂,并且(可能)更慢和/或结合了 ArrayListHashMap 的缺点。

<sup>我无法想出一种实现快速查找的方法;即没有严重缺点的方法。如果有一个好的方法,我希望Java团队会知道并将其包含在Java SE库中。这类似于为什么没有通用的并发列表类型一样。</sup>

<sup>我并不是说这是不可能的。我是说如果可能,没有人发现一种方法来实现它。据我所知。</sup>

设计通用的集合类型涉及权衡。当你优化一种访问模式时,通常会减少另一种模式的效率。

英文:

There is no Java (standard) collection type with that property.

The indexOf(Object) method is declared in List, and there are no List implementations that provide better than O(N) lookup.

There are other collection types that provide O(logN) or O(1) lookup, but they do not return a position (and index) like indexOf(Object) does. (HashMap and HashSet provide respectively get(key) and contains(object) that are O(1).)


> If there is nothing, can anyone help me out to deduce the reason why such has not been formed? Any particular reason?

Because a data structure that did provide such functionality would be complicated, and (probably) slower and/or combine the drawbacks of both an ArrayList and a HashMap.

<sup>I can't think of a good way to implement a list with fast lookup; i.e. one that didn't have serious drawbacks. And if there was a good way, I would have expected the Java team to know about it ... and to have included it in the Java SE library. This is similar to why there are no general purpose concurrent list types.</sup>

<sup>I am not saying that it is impossible. I'm saying that if it is possible, nobody has discovered a way to do it. AFAIK.</sup>

Designing an general purpose collection type involves compromise. When you optimize for one mode of access, you will often de-optimize for another.

答案2

得分: 0

为了在集合中以 O(1) 复杂度找到元素的索引,你需要能够直接检索元素的索引而无需搜索。List 或者 array 并不能做到这一点(需要 O(N) 复杂度),而 Set 是无序的1

我们只剩下 Map,但 Map键值对

你可以创建一个以元素为键、索引为值的映射作为集合的辅助数据结构。缺点是在更新集合(List/Array)时需要更新映射,

或者直接使用映射,摒弃集合。


1 indexOf 方法存在于 List 而不是 Collection 中。

英文:

To find the index of an element in a Collection in O(1) you need to be able to directly retrieve the index of the element without searching. A List or an array doesn't allow us to do this (requires O(N)) and a Set is not ordered <sup>1</sup>.

We are left with a Map but a Map is a key-value pair.

You can create a map with key as the element and value as the index as an auxiliary data structure to your collection. The downside is you need to update the map when you update your collection (List/Array)

or just use the map and get rid of your collection.


<sup>1</sup> indexOf method is on a List and not on Collection.

答案3

得分: 0

以下是翻译好的部分:

package org.example;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

public class HashList<E> {
    private final List<E> list = new ArrayList<>();
    private final Map<E, Set<Long>> indexes = new HashMap<>();

    public long indexOf(E item) {
        Set<Long> indexSet = indexes.get(item);
        if (indexSet == null || indexSet.isEmpty()) {
            return -1;
        } else {
            return indexSet.iterator().next();
        }
    }

    public void add(E item) {
        list.add(item);
        long index = list.size() - 1;
        Set<Long> indexSet = indexes.get(item);
        if (indexSet == null) {
            indexSet = new TreeSet<>();
            indexes.put(item, indexSet);
        }
        indexSet.add(index);
    }

    public static void main(String... args) {
        HashList<String> list = new HashList<>();

        assertTrue(list.indexOf("foo") == -1);
        list.add("foo");
        assertTrue(list.indexOf("foo") == 0);
        list.add("bar");
        assertTrue(list.indexOf("bar") == 1);
        list.add("foo");
        // still 0 for the first occurrence
        assertTrue(list.indexOf("foo") == 0);
    }

    private static void assertTrue(boolean truth) {
        if (!truth) {
            throw new RuntimeException();
        }
    }
}
英文:

A Map would seem to be the simplest solution, but just for fun: (implementing the rest of List is left as an exercise for the reader)

package org.example;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
public class HashList&lt;E&gt; {
private final List&lt;E&gt; list = new ArrayList&lt;&gt;();
private final Map&lt;E,Set&lt;Long&gt;&gt; indexes = new HashMap&lt;&gt;();
public long indexOf(E item) {
Set&lt;Long&gt; indexSet = indexes.get(item);
if (indexSet == null || indexSet.isEmpty()) {
return -1;
} else {
return indexSet.iterator().next();
}
}
public void add(E item) {
list.add(item);
long index = list.size() - 1;
Set&lt;Long&gt; indexSet = indexes.get(item);
if (indexSet == null) {
indexSet = new TreeSet&lt;&gt;();
indexes.put(item, indexSet);
}
indexSet.add(index);
}
public static void main(String... args) {
HashList&lt;String&gt; list = new HashList&lt;&gt;();
assertTrue(list.indexOf(&quot;foo&quot;) == -1);
list.add(&quot;foo&quot;);
assertTrue(list.indexOf(&quot;foo&quot;) == 0);
list.add(&quot;bar&quot;);
assertTrue(list.indexOf(&quot;bar&quot;) == 1);
list.add(&quot;foo&quot;);
// still 0 for the first occurrence
assertTrue(list.indexOf(&quot;foo&quot;) == 0);
}
private static void assertTrue(boolean truth) {
if (!truth) {
throw new RuntimeException();
}
}
}

huangapple
  • 本文由 发表于 2020年10月11日 20:21:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/64303948.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定