整数分区的JavaScript递归实现
问题:不重新排列的整数分区整数分区的JavaScript递归实现,javascript,algorithm,recursion,Javascript,Algorithm,Recursion,问题:不重新排列的整数分区 输入:非负数{s1,…,sn}和整数k的排列输出:将S划分为k个或更少范围的最大作业,以最小化所有范围的最大和,而不重新排序任何数字 示例输入=[100200300400500600700800900]应输出最大的作业,该作业仅为1700,因为数组最好是分区为100200300400500 | 600700 | 800900 我的功能不起作用。例如,当它应该输出1700时,它输出2400。不知道怎么了 我的代码 var integerPartitionRec=函数(n
输入:非负数{s1,…,sn}和整数k的排列
输出:将S划分为k个或更少范围的最大作业,以最小化所有范围的最大和,而不重新排序任何数字 示例输入=
[100200300400500600700800900]
应输出最大的作业,该作业仅为1700,因为数组最好是分区为100200300400500 | 600700 | 800900
我的功能不起作用。例如,当它应该输出1700时,它输出2400。不知道怎么了
我的代码
var integerPartitionRec=函数(n,k,S){
函数和(p,c){
返回p+c;
}
如果(i==1)返回S[1];
如果(k==1)返回S.slice(0,n),则减少(sum);
var成本,最小成本=Number.MAX\u值;
对于(变量i=1;i
我做了一些随机更改,现在打印1700
var integerPartitionRec = function(n, k, S) {
function sum(p, c) {
return p + c;
}
if (n === 1) return S[1];
if (k === 1) return S.slice(0, n).reduce(sum);
var cost, min_cost = Number.MAX_VALUE;
for (var i = 1; i < n; i++) {
cost = Math.max(integerPartitionRec(i, k - 1, S), S.slice(i, n).reduce(sum));
min_cost = Math.min(min_cost, cost);
}
return min_cost;
};
var run = function() {
var test = [100, 200, 300, 400, 500, 600, 700, 800, 900];
console.log(integerPartitionRec(test.length, 3, test));
};
run();
var integerPartitionRec=函数(n,k,S){
函数和(p,c){
返回p+c;
}
如果(n==1)返回S[1];
如果(k==1)返回S.slice(0,n),则减少(sum);
var成本,最小成本=Number.MAX\u值;
对于(变量i=1;i
但我更愿意使用另一种算法:您可以对答案使用二进制搜索,然后检查
O(n)
是否可以将数组划分为k
部分,其中每个部分都小于某个常数。如果我理解您的算法,它将是O(n log sum)
而不是O(n^2)
:
- 如果
您有一个大小为1的数组,无法拆分,因此最佳解决方案是不拆分并返回元素的值,该值也是整个数组的总和:n==1
(您错误地放置了S[0]
)S[1]
- 如果
无法再拆分,则返回整个数组的总和k==1
- 否则,尝试在任何可能的位置拆分(除了最开始的
和最末尾的i=0
,因为这些都是假拆分,如果可以拆分,最好这样做),检查结果如何,并采用最佳拆分i=n
但是在递归调用中,您应该只考虑到“代码< N>代码>的数组,而在代码中,在这行中:
cost = Math.max(integerPartitionRec(i, k - 1, S), S.slice(i).reduce(sum));
您考虑整个数组,因为<代码> S切片(i)。将(和)求和从i到数组的末尾,即使从<代码> N< /代码>到结束,已经在前一个调用的“尾部”中计算,所以您考虑它两次! 您可以通过告诉slice在
n
处停止来解决此问题:
cost = Math.max(integerPartitionRec(i, k - 1, S), S.slice(i, n).reduce(sum));
或者,您可以通过仅将拆分的第一部分传递给递归调用来避免使用n
:
var integerPartitionRec = function(k, S) {
function sum(p, c) {
return p + c;
}
if (k === 1 || S.length === 1) return S.reduce(sum);
var cost, min_cost = Number.MAX_VALUE;
for (var i = 1; i < S.length; i++) {
cost = Math.max(integerPartitionRec(k - 1, S.slice(0, i)), S.slice(i).reduce(sum));
min_cost = Math.min(min_cost, cost);
}
return min_cost;
};
var integerPartitionRec=函数(k,S){
函数和(p,c){
返回p+c;
}
如果(k==1 | | S.length==1)返回S.reduce(sum);
var成本,最小成本=Number.MAX\u值;
对于(变量i=1;i
这里有问题吗?还是你只是在分享你的代码?代码不起作用。对于示例输入,它应该返回1700,但返回2400如果(i==1)返回S[1];,则返回的是i
@RiaD我认为应该是n
你做了一些随机更改?我最终将其更改为cost=Math.max(integerPartitionRec(I,k-1,S,S.slice(I,n).reduce(sum))
但是你的回答告诉了我什么是错的。谢谢,这也是一个有效的解决方案,编辑了我的回答,解释了什么是错的,并显示了可能的解决方案,现在让我知道是否更清楚。
var integerPartitionRec = function(k, S) {
function sum(p, c) {
return p + c;
}
if (k === 1 || S.length === 1) return S.reduce(sum);
var cost, min_cost = Number.MAX_VALUE;
for (var i = 1; i < S.length; i++) {
cost = Math.max(integerPartitionRec(k - 1, S.slice(0, i)), S.slice(i).reduce(sum));
min_cost = Math.min(min_cost, cost);
}
return min_cost;
};