假设我有一个未排序的范围数组。 例如
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派对库和特殊的数据结构,但工作速度相当快。
你会建议什么?
答案 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)));
}
}