javascript递归为循环创建n级
我正在尝试使用javascript解决这个问题。 (对于那些不喜欢点击链接的人,这里是: 在菜单上找到所有的组合,总计15.05美元,给出以下列表:javascript递归为循环创建n级,javascript,recursion,Javascript,Recursion,我正在尝试使用javascript解决这个问题。 (对于那些不喜欢点击链接的人,这里是: 在菜单上找到所有的组合,总计15.05美元,给出以下列表: 混合水果,2.15美元 炸薯条,2.75美元 沙拉,3.35美元 热翅3.55美元 马苏里拉棒,4.20美元 取样器盘,5.80美元 我用蛮力法解决了这个问题——它丑陋、凌乱、不灵活,但我知道我的解决方案是(7个混合水果)和(2个热翅膀、1个混合水果、1个采样盘) 我希望使用递归来解决它,因为(在这个想象中的餐厅)如果某天菜单的数量改变了怎么办?或
var itemArray = [
{
"desc": "mixed fruit",
"val": 2.15,
"maxQuantity": 7
},
{
"desc": "french fries",
"val": 2.75,
"maxQuantity": 5
},
{
"desc": "salad",
"val": 3.35,
"maxQuantity": 4
},
{
"desc": "hot wings",
"val": 3.55,
"maxQuantity": 4
},
{
"desc": "mozzarella sticks",
"val": 4.20,
"maxQuantity": 4
},
{
"desc": "sampler platter",
"val": 5.80,
"maxQuantity": 3
}
];
/*maxQuantity is (15.05/val), rounded up to nearest integer, and represents
the maximum number of a single menu item before reaching 15.05 */
function doLoops (menuItemsJSON, index){
var sum= 0, lines = 0;
debugger;
if(index < 0){
return;
}
else{
for(var a = 0; a < menuItemsJSON[index].maxQuantity; a++ ){
sum += parseFloat(menuItemsJSON[index].val);
lines++;
console.log(" lines: " + lines + " index: " + index+ " maxQ: "+ (menuItemsJSON[index].maxQuantity) +" a: "+ a + ", sum: " + sum.toFixed(2));
}//end for
doLoops(menuItemsJSON, index - 1);
}//end else
return;
}
doLoops(itemArray, (itemArray.length - 1));
var itemArray=[
{
“描述”:“混合水果”,
“val”:2.15,
“最大数量”:7
},
{
“描述”:“炸薯条”,
“val”:2.75,
“最大数量”:5
},
{
“描述”:“沙拉”,
“val”:3.35,
“最大数量”:4
},
{
“描述”:“热翅膀”,
“val”:3.55,
“最大数量”:4
},
{
“描述”:“莫扎里拉棒”,
“val”:4.20,
“最大数量”:4
},
{
“描述”:“采样盘”,
“val”:5.80,
“最大数量”:3
}
];
/*maxQuantity为(15.05/val),四舍五入到最接近的整数,表示
达到15.05之前单个菜单项的最大数量*/
函数doLoops(menuItemsJSON,index){
变量和=0,行=0;
调试器;
如果(指数<0){
返回;
}
否则{
对于(var a=0;a
正如漫画中提到的,这个问题是,也就是说。这意味着所有可能解决这个问题的算法都是bruteforce(或类似于bruteforce)。除非,这是非常不可能的
所以,你可以做的是:
function doLoops(menuItemsJSON, index, targetPrice) {
if (index < 0)
return (targetPrice == 0)
else {
for(var a = 0; a < menuItemsJSON[index].maxQuantity; a++ ){
targetPrice -= parseFloat(menuItemsJSON[index].val);
if (doLoops(menuItemsJSON, index - 1, targetPrice)) { // Recursive call to look for a solution with 'a' instances of this appetizer
// We reached a solution
console.log(menuItemsJSON[index].desc + ": " + a);
return true;
}
// No solution, let's try another one
}
return false; // No solution at all
}
}
函数doLoops(menuItemsJSON、index、targetPrice){
如果(指数<0)
返回(targetPrice==0)
否则{
对于(var a=0;a
Wolfram MathWorld很好地总结了:
给定一个和一组,查找用于生成的
在本例中,总和为15.05
,权重如下:
var weights = [{
name: "Mixed Fruit",
cost: 2.15
}, {
name: "French Fries",
cost: 2.75
}, {
name: "Side Salad",
cost: 3.35
}, {
name: "Hot Wings",
cost: 3.55
}, {
name: "Mozzarella Sticks",
cost: 4.20
}, {
name: "Sampler Plate",
cost: 5.80
}];
解决背包问题的一般方法是递归的:
function solve(result, sum, weights) {
var length = weights.length;
var index = 0;
while (index < length) {
var weight = weights[index++];
var cost = weight.cost;
if (cost > sum) continue;
var newResult = result.concat(weight);
if (cost === sum) return newResult;
newResult = solve(newResult, sum - cost, weights);
if (newResult.length > 0) return newResult;
}
return [];
}
对于递归问题,我喜欢首先从基本情况开始。我建议编写方法以获取
targetAmount
参数(如果无法存储在全局可访问的位置,则可能引用菜单)。基本情况是a)如果目标金额为0,则返回true,如果目标金额为负,返回false。这些是递归成功和失败的情况
因此,唯一的另一种可能性是目标金额为正。在这种情况下,该方法应该遍历菜单项并尝试每个菜单项。它应该从目标数量中减去项目的值以获得一个新目标,并使用该新目标进行递归调用。如果该递归调用为false,则转到下一个项目-在选择此项目后,没有成功找到任何项目组合以达到新的目标金额。如果该递归调用为true,则这是最后选择的项(它将目标数量减少为0),因此将该项捆绑到一个数组中并返回它。如果该递归调用返回一个数组,则它在该路径的某个位置成功,因此将所选项取消移位到数组的前面并返回该新数组
在代码中,该方法可能如下所示
function knapsack (targetAmount) {
if (targetAmount === 0) {
return true; // base case for success
}
if (targetAmount < 0) {
return false; // base case for failure
}
for (var i = 0; i < itemArray.length; i++ ) {
var item = itemArray[i];
var itemPrice = item.val;
var newTargetAmount = targetAmount - itemPrice;
var outcome = knapsack(newTargetAmount);
if (outcome === false) {
continue; // this item failed, try the next
} else if (outcome === true) {
// for the target amount requested this item is the entire selection
return [item.desc];
} else { // received a list of items, prepend the chosen item and return
outcome.unshift(item.desc);
return outcome;
}
}
return false; // if nothing worked for this targetAmount, fail.
}
功能背包(targetAmount){
如果(targetAmount==0){
返回true;//成功的基本情况
}
如果(目标安装<0){
返回false;//失败的基本情况
}
对于(var i=0;i
如果你想得到目标数量的每一种可能的组合,而不仅仅是第一次遭遇