列表中的查找算法优于O(n²)复杂度

时间:2014-02-26 13:54:40

标签: java lookup

我正在使用java 1.6。 我有一组项目,每个项目都有一个名称和一组组件。每个组件也有一个名称。

Set<Item>

Class Item
    String name
    Set<Component>

Class Component
    String name

我现在的任务是编写一个带有输入的方法:项目名称+组件名称,输出:这一对是否存在于项目列表中。

public boolean hasItemComponentPair(String itemName, String componentName)
{
    for(Item item : getItems())
    {
        if (item.getName() == itemName)
        {
            for(Component component : item.getComponents())
            {
                if (component.getName() == componentName)
                {
                    return true;
                }
            }
        }
    }

    return false;
}

最简单的方法是简单地逐个遍历集合的元素,如果找到匹配则中断。这种方法适用于小型集合。

我的项目集通常介于5到20个项目之间,组件集大致相同。因此,有25到400个独特的项目组件对。这对数量对于天真算法来说似乎太大了,特别是如果多次调用该方法。但我也认为,对于给定数量的元素,分而治之的技术过于冗长。

这个问题通常使用哪些数据结构和算法,请记住集合的大小?

3 个答案:

答案 0 :(得分:3)

如果你可以改变你的Item类,你可以这样做:

class Item {
    String name;
    Map<String, Component> components; 
}

在上面的地图中,key是组件的名称。

将代码更改为:

public boolean hasItemComponentPair(String itemName, String componentName)
{
    for(Item item : getItems())
    {
        if (item.getName().equals(itemName))
        {
            return item.getComponents().containsKey(componentName);
        }
    }

    return false;
}

现在您只需要遍历一个集合。

答案 1 :(得分:2)

1)对列表进行排序并对它们进行二进制搜索。

2)构建索引(通常作为哈希表)。

答案 2 :(得分:1)

覆盖Item和Component类中的equals和hashCode方法,如下所示:

// Item.java
import java.util.Set;

public class Item
{
  private String name;
  private Set<Component> components;

  public Item(String name)
  {
    this.name = name;
  }

  @Override
  public int hashCode()
  {
    return name.hashCode();
  }

  @Override
  public boolean equals(Object obj)
  {
    if (obj instanceof Item)
    {
      Item item = (Item) obj;
      if (item.name != null && this.name != null)
        return item.name.equals(this.name);
    }
    return false;
  }

  public Set<Component> getComponents()
  {
    return components;
  }

  public void setComponents(Set<Component> components)
  {
    this.components = components;
  }
}

// Component.java
public class Component
{
  private String name;

  public Component(String name)
  {
    this.name = name;
  }

  @Override
  public int hashCode()
  {
    return name.hashCode();
  }

  @Override
  public boolean equals(Object obj)
  {
    if (obj instanceof Component)
    {
      Component component = (Component) obj;
      if (component.name != null && name != null)
        return component.name.equals(this.name);
    }
    return false;
  }
}

这将为您提供恒定的时间查找。因此,您可以在恒定时间内搜索元素。

以下是演示:

import java.util.HashSet;

public class SearchDemo
{
  public static void main(String[] args)
  {
    Item item1 = new Item("Item 1");
    item1.setComponents(new HashSet<Component>());
    item1.getComponents().add(new Component("Component A"));
    item1.getComponents().add(new Component("Component B"));
    item1.getComponents().add(new Component("Component C"));

    Item item2 = new Item("Item 2");
    item2.setComponents(new HashSet<Component>());
    item2.getComponents().add(new Component("Component X"));
    item2.getComponents().add(new Component("Component Y"));
    item2.getComponents().add(new Component("Component Z"));

    HashSet<Item> items = new HashSet<>();
    items.add(item1);
    items.add(item2);

    // Input from user
    String inputItem = "Item 2";
    String inputComponent = "Component Y";

    // Cast it to item and component
    Item searchItem = new Item(inputItem);
    Component searchComponent = new Component(inputComponent);

    if (items.contains(searchItem)) // Constant time search
    {
      System.out.println("Contains Item");
      for (Item item : items)
      {
        if (item.equals(searchItem))
        {
          if (item.getComponents().contains(searchComponent)) // Constant time search
          {
            System.out.println("Contains even the component");
          }
        }
      }
    }
  }
}

唯一的问题是上面查找中的for循环。 该项目可以在恒定时间内搜索,但必须在集合中再次搜索(如果它确实存在),因为我愚弄了程序,使其相信searchItem等于item在集合中。一旦找到该项并从中提取其组件集,就会对componentItem进行恒定时间搜索。 如果HashMap课程中有Component ItemSet,而不是HashMapname中的每个关键字都是component {{1}}的{​​},然后可以在恒定时间内搜索用户的输入!