假设我想对排序后随机选择的项目1到10进行排序,选择与每个数字的权重相关联的概率(即1的权重= 10,2 = 30,4 = 15,5 = 35,6 = = 10,其余0);假设我在此之前已经计算了权重之和。现在,我首先必须根据它们的权重对数字进行排序,然后再次通过列表将每个数字除以所有数字的总和(即规范化以使每个权重在[0,1]中)。排序然后遍历列表很慢,所以我尝试将权重放在compareTo()
方法中,以便在排序时进行规范化,但如果我这样做,Collections.sort()不会将它们按正确顺序排列。任何建议(除了必须从头开始编写我自己的高效排序算法)?我希望我很清楚。
答案 0 :(得分:1)
是什么让您认为您需要按重量排序以随机选择数字?
我会这样做:
int[] numbers;
int[] weight;
int totalweight;
for (int n : numbers) {
totalweight += weight[n];
}
int t = new Random().nextInt(totalWeight);
for (int n : numbers) {
t -= weight[n];
if (t < 0) return n;
}
如果您从同一个数组中重复选择,您可能希望预先计算部分总和并对其进行二元搜索。
如果您的数组包含范围明显小于其长度的数字,您可以调整计数排序的想法,即为每个不同数字预先计算部分和,并对这些数字进行二元搜索。
很容易看出,除非您对所涉及的数字或权重有一些先验知识,否则您需要查看每个数字的权重(因为它可能使所有其他权重相形见绌),因此一般算法必须采用至少O(n)。
但是,其他约束允许更有效的实现。如果你知道一个数字的重量相当小的上限,你可以进行A / R采样:
int[] numbers;
int[] weight;
int maxWeight;
Random r = new Random();
do {
c = numbers[r.nextInt(numbers.length)];
} while (r.nextInt(maxWeight) > weight[c]);
return c;
答案 1 :(得分:1)
假设ints
是List
:
Collections.sort(ints, new Comparator<Integer> () {
private int getWeight(Integer i) {
int weight = 0;
switch(i) {
case 1:
case 6: weight = 10; break;
case 2: weight = 30; break;
case 4: weight = 15; break;
case 5: weight = 35; break;
}
return weight;
}
public int compare(Integer i1, Integer i2) {
int w1 = getWeight(i1);
int w2 = getWeight(i2);
return (w1>w2)?1:(w1==w2?0:-1);
}});
for(int i:ints) {
System.out.print(i+",");
}
您可以使用枚举或散列图来存储数字的权重,代码是如何进行基于权重的比较的示例。
答案 2 :(得分:0)
只是建议改进Meriton的优秀建议:
如果你想让第一部分更快,你可以创建一个索引,以便减少循环所需的元素。对于计算权重时的每个N数,记下数组/哈希中的索引和到目前为止的总和。
然后当您选择要循环的数字t时,您可以在索引中查找并跳转将元素传递到那里。如果您有大量条目和多次查找,可能会节省您的时间。