Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';这是均匀填写未排序列表的最有效方法;“桶”;大小不一_C++_Algorithm - Fatal编程技术网

C++ 什么';这是均匀填写未排序列表的最有效方法;“桶”;大小不一

C++ 什么';这是均匀填写未排序列表的最有效方法;“桶”;大小不一,c++,algorithm,C++,Algorithm,假设我有一个未排序的buckets列表。(每个桶都有一个size属性。)假设我有一个数量Q,我必须尽可能均匀地分布在桶列表中(即最小化最大值) 如果桶的大小越来越大,那么解决方案就显而易见了:将每个桶装满,比如说bucket[i],直到Q/(bucket.length-i)size,然后用相同的数量将剩余的桶装满,Q/(bucket.length-i),如图所示: 如果桶未分类,解决此问题的最有效方法是什么? 我只能想到这样的迭代(伪代码): 但我不确定是否有更好的方法,或者对列表进行排序是否

假设我有一个未排序的
bucket
s列表。(每个桶都有一个
size
属性。)假设我有一个数量
Q
,我必须尽可能均匀地分布在桶列表中(即最小化最大值)

如果桶的大小越来越大,那么解决方案就显而易见了:将每个桶装满,比如说
bucket[i]
,直到
Q/(bucket.length-i)size
,然后用相同的数量将剩余的桶装满,
Q/(bucket.length-i)
,如图所示:

如果桶未分类,解决此问题的最有效方法是什么?

我只能想到这样的迭代(伪代码):

但我不确定是否有更好的方法,或者对列表进行排序是否更有效


(我面临的实际问题还有更多,例如,此“未排序”列表实际上是按单独的属性“rank”排序的。),它决定了当数量不均匀分配时,哪些桶会得到额外的填充,等等。因此,例如,要使用先排序后填充的方法,我会按桶大小和等级对列表进行排序。但是知道这个问题的答案会帮助我解出其余的问题。)

为什么需要对桶列表进行排序? 只需在桶上迭代两次

第一次把所有的尺码都数一下。由此你可以说,“我希望每个桶里有K件物品”


第二次,把桶装满。

另一个想法如下。确定每个存储桶的平均项目数。然后试着用这个数字填满所有的桶(一般来说,不是所有的桶都能容纳那么多的物品)

之后,您将有许多剩余的项放置在bucket中(因为并非所有项都适合上一次迭代),以及一个bucket列表,其中可以容纳比当前包含的项更多的项(在上一次迭代中计算)

同样,根据要分发的剩余项目数,计算剩余存储桶上要分发的平均项目数

重复此操作,直到放置所有项目


我期望运行时间为
O(n*logn)
,但没有分析它。它的运行时间与排序-然后填充方法相同,但是,如果您的存储桶只有有限数量的不同大小,例如:一些小,一些大,一些大。

在许多情况下,如果对数据进行排序,则解决方案“非常简单”或“非常有效”,然而,如果不是非常复杂或无效,那么最好的解决方案通常是先对数据进行排序,然后选择简单、有效的解决方案。尽管这意味着您需要先对数据进行排序,但有很多非常好的排序算法可用于几乎任何目的,在许多情况下,“先对数据进行排序,然后对其应用简单有效的算法”的总开销仍然低于“未对数据进行排序,并对其应用非常复杂、无效的算法”


您需要按不同键排序的数据这一事实对我来说只意味着,这里需要两个列表,每个列表按不同的标准排序。除非我们在这里讨论数千个存储桶,否则第二个列表的内存开销很可能不会成为问题(所有这两个列表都只包含指向bucket对象的指针,这意味着每个指针有4/8字节,具体取决于您是否有32位或64位代码)。一个列表按大小排序bucket,另一个列表按“秩”排序bucket,当添加问题中描述的新项时,您使用“按大小排序”列表,而使用“按等级排序”列表的方式与您现在使用的方式相同。

我认为这在线性时间内是可能的,但是我被困在某个点上。也许您可以解决问题,也许用这种方式无法解决问题

考虑以下算法

基于二进制搜索,我们希望找到未完全填满的最小存储桶。在存储桶列表中找到这样一个存储桶在线性时间内是可能的,但正如我所说的,我被困在这里。一旦找到了该存储桶,其余的就变得微不足道了,因为对于所有较小的存储桶,我们将其大小相加,从项目总数中减去它到be放置,除以大于或等于我们刚刚找到的桶的桶数

下面是解决这个问题的一个尝试:没有完全填满的最小桶是什么?该算法是由QuickSelect驱动的

选择一个枢轴桶。看看它是比我们要找的桶小还是大。(这个步骤很简单。)

  • 如果较小,则将小于或等于此值的所有存储桶的大小相加,从项目总数中减去此总和,然后在包含所有较大存储桶的集合上继续搜索

  • 如果它更大,我们将不得不做类似的事情,但是现在减去所有比这个大的存储桶中放置的项目数。我们不知道这些存储桶中放置的项目数。这就是问题所在……但是如果我们知道,我们将继续搜索包含所有较小存储桶的集合


如果此算法有效,它将在随机轴元素的预期线性时间内运行(请参阅QuickSelect)。

如果您可以确定q,则填充每个桶的适当最低液位,使总值为q,而不是线性解:

for (bucket b : buckets)
{
    int f = max(b.capacity(), q);
    b.fill(f);
}
所以问题是确定q级

您可以对q进行二进制搜索。也就是说,我们知道q是介于
min(b.capacity)
max(b.capacity)
之间的整数。即:

  • 从最小(容量)和最大(容量)之间的中间位置开始
  • 通过桶计算使用
    Q'
  • for (bucket b : buckets)
    {
        int f = max(b.capacity(), q);
        b.fill(f);
    }
    
    unordered_set<int,int> bucket_capacity;
    
    for (bucket b : buckets)
        bucket_capacity[b.capacity]++;