Algorithm 如何在添加新值时保持常量百分比

Algorithm 如何在添加新值时保持常量百分比,algorithm,percentage,Algorithm,Percentage,我想做一个算法,用理想的百分比将实体的总数分配到不同的类别中。比如说,第一类应该包含所有实体的50.3%,第二类-34.3%,第三类-15.4% 在某些理想条件下,一切都是好的。我很容易计算每个类别的实体的期望值,然后使用类似的算法来保持正确的总和。 小例子: All categories are empty We are adding 100 To the first 50 To the second = 34 To the third = 16 (fixed by current algor

我想做一个算法,用理想的百分比将实体的总数分配到不同的类别中。比如说,第一类应该包含所有实体的50.3%,第二类-34.3%,第三类-15.4%

在某些理想条件下,一切都是好的。我很容易计算每个类别的实体的期望值,然后使用类似的算法来保持正确的总和。 小例子:

All categories are empty
We are adding 100
To the first 50
To the second = 34
To the third = 16 (fixed by current algorithm, was 15)
但是,在某一点上,类别已经可以包含一些实体,而这些实体并不是按照我们理想的百分比分布的!我不知道在这种情况下应该使用什么算法。此算法应使用以下规则分发新实体:

添加后,我们应尽可能接近理想百分比。理想百分比和实际百分比之间的偏差应最小且彼此接近。 算法无法从任何类别中删除现有实体。它应该只分发新的。 例如:

At start:
First is empty
Second contains 10
Third contains 40

We are adding 50
To the first 38
To the second 12
To the third 0 (too much entities here before adding)

Result:
First = 38; deviation = 12.3%
Second = 22; deviation = 12.3%
Third = 40; deviation = 24.6%
不要问我是怎么得到38和12的,我只是尝试了不同的组合,直到它看起来是正确的。
关于算法有什么想法吗?

以下方法可能有效。假设您维护3个列表,每个类别1个,以及一个正在运行的平均值,即列表和总元素的当前平均值。需要另外两个元素来确保添加元素的复杂性保持不变

数据结构:

算法:


希望能有帮助

@Wolfie算法是一个完全可以接受的标记。您可以选择任何适合您回答的语言,只要步骤明显。感谢Mark,我们不确定我们的项目不包含任何值,因此我们无法计算类别平均值。但我相信这个算法是我们需要的。我们将用类似于当前类别百分比的内容替换catAvg,并尝试实现这一点。谢谢你的回答。
category_list {
    items : []
    average : float
    count : int
}

category_list categories[3]; # 1 for each category
avg_distribution[3]; # this will hold the distribution allowed for each category
addItems(int items[]) {
   for item in items:
     category = getCategory(item)
     insertItem(category, item)
}

# This algo will identify the category to be inserted in constant time or the no.of categories available. 
# For this scenario we can say it runs in O(1)
int getCategory(int item) {
   minAvg = INT_MAX
   minCat = 0
   for cat in range(3):
      category = categories[cat]
      newAvg = (category.avg*(category.count)+item.value) / (category.count+1)
      newAvg = newAvg - avg_distribution[cat] 
      # this is to make sure we consider only the deviation part and not the entire avg.
      if newAvg < minAvg:
         minAvg = minAvg
         minCat = cat 

   return minCat
}

# This will insert item in a given category in O(1)
insertItem(category, item) {
    category.items[category.count] = item.value
    category.avg = (category.avg*(category.count)+item.value) / (category.count+1)
    category.count++;
}

# This method is need to initially load all the elements in given category
loadAllItems(int items[], int category) {
    category = categories[category]
    for item in items:
       insertItem(category, item)
}