Performance 将数字拆分为和分量
是否有一种有效的算法将一个数字拆分为Performance 将数字拆分为和分量,performance,algorithm,math,numbers,sum,Performance,Algorithm,Math,Numbers,Sum,是否有一种有效的算法将一个数字拆分为N子部分,从而使这些数字的总和与原始数字相加,且基数最小?例如,如果我想将50分为7个子部分,并且最小基数为2,我可以执行10,5,8,2,3,5,17(以及任何其他数量的组合)。我希望将数字保持为整数,并且相对随机,但我不确定如何有效地生成与原始数字相加的数字,并且不包括低于给定最小值的数字。有什么建议吗 编辑-只是为了复制/粘贴我的评论,整数不必是唯一的,但我希望避免每次都使用相同大小的整数(例如,将50个整数拆分为10个相同大小)。通过从数字中减去最小次
N
子部分,从而使这些数字的总和与原始数字相加,且基数最小?例如,如果我想将50分为7个子部分,并且最小基数为2,我可以执行10,5,8,2,3,5,17
(以及任何其他数量的组合)。我希望将数字保持为整数,并且相对随机,但我不确定如何有效地生成与原始数字相加的数字,并且不包括低于给定最小值的数字。有什么建议吗
编辑-只是为了复制/粘贴我的评论,整数不必是唯一的,但我希望避免每次都使用相同大小的整数(例如,将50个整数拆分为10个相同大小)。通过从数字中减去最小次数N,生成N个子部分并添加最小值,可以轻松删除最小值的要求。在您的示例中,问题归结为将36拆分为7个整数,您已经给出了拆分8,3,6,0,1,3,15
解决方案的其余部分取决于“相对随机”需求的性质。对于一些最小的随机性,考虑在0和未分裂部分之间顺序选择数字(例如,在0到36之间,获得8,然后在0和28之间,获得3,等等7倍)。如果这还不够,您需要首先定义随机性。这里是一个伪随机解决方案[请注意,解决方案可能有偏差,但相对随机]
input:
n - the number we should sum up to
k - the number of 'parts'
m - minimum
(1) split n into k numbers: x1,x2,...,xk such that x1+...+xk = n, and the numbers
are closest possible to each other [in other words, x1 = x2 = ... = n/k where
possible, the end might vary at atmost +-1.]
(2) for each number xi from i=1 to k-1:
temp <- rand(m,xi)
spread x - temp evenly among xi+1,...,xk
xi <- temp
(3) shuffle the resulting list.
输入:
n-我们应该总结的数字
k-部件的数量
m-最小值
(1) 将n分成k个数:x1,x2,…,xk,使x1+…+xk=n,然后
可能彼此最接近[换句话说,x1=x2=…=n/k,其中
可能的情况下,端部可能在atmost+-1处变化。]
(2)对于每个数席,从i=1到k-1:
这里有一个算法:
将N
除以m
,其中N
是您的编号,m
是子部分的编号
将结果向下舍入到最接近的值,并将该值分配给所有子部分
在每个小节中添加一个,直到值相加为N
。在这一点上,如果N
是50,m
是7,那么就有8,7,7,7,7,7
从0迭代到m-1
,步进2,然后在-(currentValue base)
和currentValue base
之间添加一个随机数。将该数字的倒数加到相邻的桶中。如果存储桶的数量为奇数,则在最后一个存储桶上,以类似于上面步骤2和步骤3的分布式方式将其添加到所有其他存储桶,而不是将该数字的倒数添加到其相邻的存储桶上
性能:
第一步是O(1)
,第二步、第三步和第四步是O(m)
,所以总的来说是O(m)
,我想出了一些“只是为了好玩”的东西
它从最小值
递增到数字
,并使用模和随机数将N
节填充到数组中
如果这个数字有太多的部分,它将不会像预期的那样工作。(即number
)下面是一个创建请求的数字重新分区的java代码示例。它是递归的方法,我们把问题分解成2个子问题:如果我们想把一个数字分解成n个篮子中的一个分量的总和,那么我们尝试一次考虑一个子数,并且他们中的每一个将剩余的分解中的发现委托给递归调用(N-1)筐之间的重新分配。
处理特定子编号(在for循环中)时会考虑请求的阈值
import java.util.ArrayList;
导入java.util.List;
公共类测试数据{
公共静态列表计算机分区号(整数分解、整数子数、整数阈值){
List resultRec=新建ArrayList();
if(子编号的编号==1){
List resultEnd=new ArrayList();
ArrayList酉=新的ArrayList();
结果。添加(单一);
酉.加法(数_到_分解);
返回结果;
}
对于(int i=阈值_数;i
现在,如果你想让最小数是2以外的其他值,把它改为任何值,只要提供子部分的数量*最小随机数\u所需我知道已经有很长一段时间了,但我想添加我的答案来帮助某人这里是我使用递归的代码
#include <stdio.h>
#include <stdlib.h>
void print(int n, int * a) {
int i ;
for (i = 0; i <= n; i++) {
printf("%d", a[i]);
i < n ? printf(" + ") : printf("");
}
printf("\n");
}
void integerPartition(int n, int * a, int level){
int first;
int i;
if (n < 1) return ;
a[level] = n;
print(level, a);
first = (level == 0) ? 1 : a[level-1];
for(i = first; i <= n / 2; i++){
a[level] = i;
integerPartition(n - i, a, level + 1);
}
}
int main(int argc, char ** argv){
int n = 10;
int * a = (int * ) malloc(sizeof(int) * n);
integerPartition (n, a, 0);
return(0);
}
#包括
#包括
无效打印(整数n,整数*a){
int i;
对于(i=0;i让我用Python编写它
假设您有50个元素要拆分为7个框,并且每个框中至少要有两个
N_init = 50
s = 2
m = 7
默认情况下,我们在每个框中放置s个元素,因此剩下N个元素
N = N_init - s*m
我们画m个随机数,对它们进行排序,在后面加上N。这就像在一本N页的书中随机插入m个书签一样。
连续书签之间的页数是随机的。(我们有s,这样我们可以确保每个框至少有s个元素)
完成了!我正在做类似的事情,下面是我的想法
您可以在O(N-1)中的每个步骤中使用一些计算来完成此操作。首先,您可以在每个点的最小数量和最大数量之间选择一个随机数。对于每个点,最大数量通过从剩余余额中减去(最小数量*剩余数量)来计算
例如:对于第一个点,您选择一个介于2和38之间的数字。您可以通过从50中减去(7-1)*2得到该值。即50-12=38
一旦你选择了一个数字,比如说19,那么下一个点的范围是2-21,即50-19-(5*2)=21
…等等
以下是代码片段:
function splitNumIntoXRandomComponents(num, x, min_num) {
var components = [];
var count = 1;
var cumulative = 0;
var balance = num;
for (var i = 0; i<x-1; i++) {
//max num for this spot
var max_num = balance - ((x-count)*min_num);
//to avoid big numbers in the beginning and min numbers at the end
if (Math.random() > 0.5){ //0.5 can be tuned to your liking
max_num = Math.floor(max_num / 2) + min_num;
}
//generate the number for the spot at 'count'
var c = Math.floor(Math.random()*(max_num-min_num+1)+min_num);
//adjust balances
cumulative += c;
balance -= c;
count++;
//store this number
components.push(c);
}
//push remaining balance into the last spot
components.push(balance);
//print numbers
console.log(components);
}
for (var i=0; i<10; i++) {
splitNumIntoXRandomComponents(50, 7, 2);
}
以下是JSFIDLE:
子集和:给定一组数字,找到一个和特定数字相加的子集。您的问题:给定一个数字,找到和它相加的对应子集。我是
N = N_init - s*m
a = sorted([random.randint(0,N+1) for i in range(m)])
a.append(N)
result = [j-i+s for(i,j) in zip(a[0:m],a[1:m+1])]
function splitNumIntoXRandomComponents(num, x, min_num) {
var components = [];
var count = 1;
var cumulative = 0;
var balance = num;
for (var i = 0; i<x-1; i++) {
//max num for this spot
var max_num = balance - ((x-count)*min_num);
//to avoid big numbers in the beginning and min numbers at the end
if (Math.random() > 0.5){ //0.5 can be tuned to your liking
max_num = Math.floor(max_num / 2) + min_num;
}
//generate the number for the spot at 'count'
var c = Math.floor(Math.random()*(max_num-min_num+1)+min_num);
//adjust balances
cumulative += c;
balance -= c;
count++;
//store this number
components.push(c);
}
//push remaining balance into the last spot
components.push(balance);
//print numbers
console.log(components);
}
for (var i=0; i<10; i++) {
splitNumIntoXRandomComponents(50, 7, 2);
}
[34, 2, 4, 3, 3, 2, 2]
[14, 12, 8, 8, 4, 2, 2]
[7, 4, 26, 5, 2, 3, 3]
[8, 2, 16, 4, 4, 9, 7]
[20, 8, 4, 4, 7, 4, 3]
[3, 34, 4, 2, 2, 2, 3]
[10, 5, 15, 2, 7, 5, 6]
[6, 3, 10, 4, 10, 3, 14]
[31, 4, 2, 3, 5, 2, 3]
[7, 5, 2, 9, 9, 2, 16]