我需要提出一个执行以下操作的算法:
假设您有一系列正数(例如[1,3,7,0,0,9]
)并且事先知道它们的总和是20。
您希望从每个数字中抽取一些平均金额,以使新金额少于7。
为此,您必须遵循以下规则:
减法越均匀地分布在数组上越好。
这是我尝试使用JavaScript +下划线的算法(这可能会使它成为n ^ 2):
function distributeSubtraction(array, goal){
var sum = _.reduce(arr, function(x, y) { return x + y; }, 0);
if(goal < sum){
while(goal < sum && goal > 0){
var less = ~~(goal / _.filter(arr, _.identity).length); //length of array without 0s
arr = _.map(arr, function(val){
if(less > 0){
return (less < val) ? val - less : val; //not ideal, im skipping some!
} else {
if(goal > 0){ //again not ideal. giving preference to start of array
if(val > 0) {
goal--;
return val - 1;
}
} else {
return val;
}
}
});
if(goal > 0){
var newSum = _.reduce(arr, function(x, y) { return x + y; }, 0);
goal -= sum - newSum;
sum = newSum;
} else {
return arr;
}
}
} else if(goal == sum) {
return _.map(arr, function(){ return 0; });
} else {
return arr;
}
}
var goal = 7;
var arr = [1,3,7,0,0,9];
var newArray = distributeSubtraction(arr, goal);
//returned: [0, 1, 5, 0, 0, 7];
嗯,这有效,但必须有更好的方法!我想,对于更大的数组和更大的数字,这个东西的运行时间会很糟糕。
编辑:我想澄清这个问题纯粹是学术性的。可以把它想象成一个面试问题,在这个问题上你可以使用白板,面试官会问你算法在不同类型的数据集上的行为。
答案 0 :(得分:1)
听起来你想从每个数字中减去加权数量。 I.E您想从每个项目中减去X/sum * amount_to_subtract
。你当然需要减去你减去的金额。问题是确保你减去了正确的总金额。此外,这取决于您的输入:您是否保证减去减去的金额?这是一个粗略的python实现,(我认为):
def uniform_array_reduction(inp, amount):
total = sum(inp)
if amount > total:
raise RuntimeError('Can\'t remove more than there is')
if amount == total: #special case
return [0] * len(inp)
removed = 0
output = []
for i in inp:
if removed < amount:
to_remove = int(round(float(i)/float(total)*float(amount)))
output.append(i - to_remove)
removed += to_remove
else:
output.append(i)
# if we didn't remove enough, just remove 1 from
# each element until we've hit our mark.
# shouldn't require more than one pass
while removed < amount:
for i in range(len(output)):
if output[i] > 0:
output[i] -= 1
removed += 1
if removed == amount:
break
return output
编辑:我修复了代码中的一些错误。
答案 1 :(得分:1)
s = Sum(x) - required_sum
do:
a = ceil( s/number_of_non_zeros(x) )
For i=1 to length(x):
v = min(a, x[i], s)
x[i]-=v
s-=v
while s>0
此版本无需排序。