使用Java有效地将已排序的ArrayList放入已排序的数据结构中并查找小于x的数量

时间:2015-09-04 10:17:40

标签: java sorting data-structures tree

我有一个已经排序的数组列表。我希望将它放在一个排序的数据结构中,以便我可以轻松找到小于指定数量的项目数。

这就是我到目前为止的做法:

TreeSet<Integer> sortedList = new TreeSet<>(myArrayList); // This is slow

如果我想找到小于或等于50的数字(例如),那么我会这样做:

sortedList.headSet(50, true).size(); // This is not that slow

所有这些看起来都非常低效。这主要是因为myArrayList已经排序并且初始化TreeSet非常慢。

请注意,数组列表非常大,查询数量非常少(大约10个)。

1 个答案:

答案 0 :(得分:3)

如果您的myArrayList已经排序且不包含重复项,则二进制搜索就是您的朋友。使用Collections.binarySearchbinarySearch返回现有元素的索引(因此您有idx+1个元素小于或等于)或插入点,其中应插入给定元素(所以{{1}是严格少于,没有相等元素的元素数量。

-idx-1

用法示例:

public static int countLessOrEqual(List<Integer> nums, int limit) {
    int idx = Collections.binarySearch(nums, limit);
    if(idx < 0) return -idx-1;
    return idx+1;
}

如果您的输入列表已排序但包含重复项,则所有重复项都是相邻的,因此您可以预先处理列表并删除它们(比构建List<Integer> nums = Arrays.asList(1, 10, 23, 31, 50, 65, 71, 89, 100); System.out.println(countLessOrEqual(nums, 50)); // 5 System.out.println(countLessOrEqual(nums, 51)); // 5 System.out.println(countLessOrEqual(nums, 49)); // 4 System.out.println(countLessOrEqual(nums, 0)); // 0 System.out.println(countLessOrEqual(nums, 300)); // 9 要快得多):

TreeSet

用法示例:

public static List<Integer> removeAdjacentDuplicates(List<Integer> input) {
    List<Integer> result = new ArrayList<>();
    Integer last = null;
    for(int i=0; i<input.size(); i++) {
        Integer cur = input.get(i);
        if(i == 0 || !cur.equals(last))
            result.add(cur);
        last = cur;
    }
    return result;
}
相关问题