查找值在Java中的范围

时间:2013-09-28 08:01:23

标签: java collections

假设我有一个未排序的范围数组。 例如

class CreditRange{
   long credits;
   int id;
}

现在我想找到,给定信用计数值属于CreditRange中的哪一个。

可能Set<CreditRange>的值可以是

CreditRange :{id:1,credits:0}
CreditRange :{id:2,credits:100}
CreditRange :{id:3,credits:500}
CreditRange :{id:4,credits:250}
  

案例1:现在当用户输入Credits = 50时,此范围比较器应该给出   回答为

CreditRange :{id:1,credits:0}

  

案例2:现在当用户输入Credits = 300时,此范围比较器应该给出   回答为

CreditRange :{id:4,credits:250}

  

案例3:现在当用户输入Credits = 600时,此范围比较器应该给出   回答为

CreditRange :{id:3,credits:500}

我们可以假设范围数组需要大约1M并且适合内存。我正在寻找一种简单的算法,它只使用标准的JDK集合,没有任何3d派对库和特殊的数据结构,但工作速度相当快。

你会建议什么?

2 个答案:

答案 0 :(得分:8)

我猜,这不是你所说的范围。相反,你想要的最大元素小于你传递的元素。

您可以按照以下步骤解决问题:

  • 首先为您的班级实施Comparator,并根据学分
  • 进行比较
  • 然后,使用TreeSet,将该比较器的实例传递给它的构造函数。它将根据比较器对其中的项目进行排序。
  • 然后根据比较器使用TreeSet#floor(E)方法获得小于E的最大元素。当然,您必须创建CreditRange的对象才能进行搜索。您不能只搜索300

演示代码:

NavigableSet<Integer> set = new TreeSet<>();
set.add(0);   set.add(100);
set.add(250); set.add(500);

System.out.println(set.floor(50));  // 0
System.out.println(set.floor(300)); // 250

请重命名你的班级。它没有以任何方式描绘范围。它应该更好地命名为CreditBound,由Jon Skeet在评论中指定。

答案 1 :(得分:2)

正如Rohit所提到的,一种简单的方法是使用TreeSet底层(另一种方法是实现二进制搜索的修改变体。这是一个更完整的答案:

package test;

import java.util.TreeSet;

class CreditRange implements Comparable<CreditRange> {
  long credits;
  int id;

  public CreditRange(int id, long credits) {
    this.id = id;
    this.credits = credits;
  }

  public CreditRange(long credits) {
    this.id = -1;
    this.credits = credits;
  }

  @Override
  public int compareTo(CreditRange o) {
    return credits < o.credits ? -1 : credits > o.credits ? 1 : 0;
  }

  @Override
  public String toString() {
    return "id:" + id + ", credits:" + credits;
  }
}

public class Test {
  public static void main(String[] args) {
    TreeSet<CreditRange> set = new TreeSet<>();
    set.add(new CreditRange(1, 0));
    set.add(new CreditRange(2, 100));
    set.add(new CreditRange(3, 500));
    set.add(new CreditRange(4, 250));
    System.out.println(set.floor(new CreditRange(50)));
    System.out.println(set.floor(new CreditRange(300)));
    System.out.println(set.floor(new CreditRange(600)));
  }
}