将复杂性从O(n)改为o(logn)

时间:2016-12-15 20:37:40

标签: java data-structures

我们有一个名为ratings的链表,其中包含3个整数 userId,ItemId和实际评级的值(例如0到10) 此方法实际上返回程序从文件读取的用户i和项目j 的评级,如果没有评级则返回-1

BigOh(n)的方法:

public int getRating(int i, int j){
    ratings.findFirst();
    while(!ratings.empty()){
        if(ratings.retrieve().getUserId() == i && ratings.retrieve().getItemId() == j)
            return ratings.retrieve().getValue();
        else 
            ratings.findNext();
    }
    return -1;  
}

如何在BigOh(logn)中执行此操作?
或者,无论如何我可以使用二进制搜索树来解决它?

3 个答案:

答案 0 :(得分:0)

您可以使用散列来完成 O(1)中的任务。请阅读此article以深入了解哈希。

由于您使用的是Java,因此可以使用HashMap来完成任务。请注意,hashing技术的最差情况时间复杂度为 O(log n),但平均而言 O(1)。如果您对哈希表和摊销分析更感兴趣,请仔细阅读article

代码示例:您可以使用所需属性创建Class,并按如下方式实施equalshashCode方法。 [阅读Java collections - hashCode() and equals()]

class Rating {

    public int user_id; // id of the user who rated
    public int item_id; // id of the item being rated

    public Rating(int user_id, int item_id) {
        this.user_id = user_id;
        this.item_id = item_id;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof Rating)) {
            return false;
        }
        Rating ratingObj = (Rating) o;
        return ratingObj.user_id == user_id
                && ratingObj.item_id == item_id;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + user_id;
        result = 31 * result + item_id;
        return result;
    }
}

然后将值存储在HashMap中,如下所示:

public static void main(String[] args) {
    HashMap<Rating, Integer> ratingMap = new HashMap<>();
    Rating rt = new Rating(1, 5); // user id = 1, item id = 5
    ratingMap.put(rt, 3);
    rt = new Rating(1, 2); // user id = 1, item id = 2
    ratingMap.put(rt, 4);
    rt = new Rating(1, 3); // user id = 1, item id = 3
    ratingMap.put(rt, 5);

    // now search in HashMap
    System.out.println(ratingMap.get(new Rating(1, 3))); // prints 5
}

答案 1 :(得分:0)

如上所述,这很难在O(log n)中完成。您正在查看元素,直到找到所需的元素。在最坏的情况下,在循环结束之前,您将找不到所需的元素,从而使其成为O(n)。

当然,如果ratings是一个字典,你将检索几乎为O(1)的值:用户ID作为键,例如作为值的评级列表。插入会有点慢但不多。

答案 2 :(得分:0)

简短的回答是:使用不同的数据结构。链接列表不能在任何其他中进行搜索,而不能在线性时间内进行搜索,因为每个元素都链接在一起而没有任何真实的相似性或顺序(如果列表已经排序,甚至 ,你仍然需要一些类型的定时遍历。)

您可以使用的一个数据结构是来自Guava的Table。使用此数据结构,您必须做更多工作才能添加元素...

Table<Integer, Integer, Rating> ratings = HashBasedTable.create();
ratings.put(rating.getUserId(), rating.getItemId(), rating);

...但您可以快速检索非常 - 大约在HashBasedTable支持LinkedHashSet<Integer, LinkedHashSet<Integer, Rating>>后的大约O(1)时间。

ratings.get(i, j);