2017-02-26 189 views
0

我想解决codewars网站上的算法。作为一名初学者,我很难实现各种编程技术,缺乏基本的编程概念,如范围,提升等。无论如何,我决心解决问题。如何正确实现递归算法?

的说明说:

写功能,持久性,这发生在一个正参数NUM并返回其乘持久性,这是你必须乘位数NUM的次数,直到你达到单个数字。

persistence(39) === 3 // because 3*9 = 27, 2*7 = 14, 1*4=4 
          // and 4 has only one digit 
persistence(999) === 4 // because 9*9*9 = 729, 7*2*9 = 126, 
          // 1*2*6 = 12, and finally 1*2 = 2 
persistence(4) === 0 // because 4 is already a one-digit number 

现在我只是想实现这一目标的结果3*9 = 27, 2*7 = 14, 1*4=4但是我被困。我知道我错过了一些事情,请给我一些宝贵的建议!

我的代码如下所示:

function persistence(num) { 
    var total = 1; 
    var step = 0; 
    var number = multiple(num); 
    while (step < 3) { 
     for (var i = 0; i < number.length; i++) { 
      total *= splitNumbers[i]; 
     } 
     multiple(number); 
     step += 1; 
    } 
} 

function multiple(num) { 
    var splitNumbers = num.toString().split(''); 
    var a = splitNumbers[0]; 
    var b = splitNumbers[1]; 
    return a * b; 
} 
persistence(39); 
+0

*号*是一个数字。数字没有长度属性,所以'我 RobG

+0

好的,谢谢你,我没注意到)) – NZMAI

回答

2

奇怪的是,在第二个功能你计算产品(忽略除前两个全数位),然后在主函数,你把它当作一个字符串(它不是),并开始再次乘以这些数字。这不是递归原则:你应该只做一次动作,然后进行递归调用。

这里是一个解决方案:

function persistence(num) { 
 
    var digits = getDigits(num); 
 
    if (digits.length === 1) return 0; // number has only 1 digit, so we're done 
 
    var product = getProduct(digits); 
 
    return 1 + persistence(product); // we performed one transformation, now recurse 
 
} 
 

 
function getDigits(num) { 
 
    return num.toString().split('').map(Number); // convert chars to numbers 
 
} 
 

 
function getProduct(nums) { 
 
    return nums.reduce(function (a, b) { // nice way to get 1 result from array 
 
     return a * b; 
 
    }, 1); 
 
} 
 

 
console.log(persistence(39));

+0

非常感谢! – NZMAI

1

开始,如果你的条件得到满足,返回结果的单一功能(只有一个数字左)。如果不存在,则返回下一个迭代的结果,传入要跟踪的状态(当前计数)。也许是这样的:

function persistence(num, opt_count) { 
 
    num = parseInt(num, 10); // Assume we're dealing with only ints. 
 
    var count = opt_count || 0; // Count is optional, so make sure we init. 
 

 
    if (num > 9) { 
 
    var digits = String(num).split(''); // Split our number as string. 
 
    num = digits.shift(); 
 
    do { 
 
     num *= digits.shift(); // Note, multiplication will cast back automatically. 
 
    } while(digits.length); 
 
    count++; // Increment our count 
 
    } 
 

 
    if (num < 10) return count; // Return our count if we're under 10. 
 
    return persistence(num, count); // Recurse with our current state. 
 
} 
 

 
console.log('39: ' + persistence(39));  // 3 
 
console.log('999: ' + persistence(999)); // 4 
 
console.log('4: ' + persistence(4));  // 0

+0

谢谢你的解释! – NZMAI

+0

do num_ = digits.shift(); } while(digits.length); count ++; } 很好的实施!我应该考虑到它!是否可以在其他情况下使用某种编程模式? – NZMAI

1

有代码中的几个问题:

function persistence(num) { 
 
    var total = 1; 
 
    var step = 0; 
 
    // This will return a number 
 
    var number = multiple(num); 
 

 
    while (step < 3) { 
 
     // Here number is a number, which doesn't have a length property so 
 
     // the loop never runs. However, once you fix that... 
 
     for (var i = 0; i < number.length; i++) { 
 

 
      // splitNumbers is in the multiple function, you can't access it 
 
      // from this function 
 
      total *= splitNumbers[i]; 
 
     } 
 
     multiple(number); 
 
     step += 1; 
 
    } 
 
    // The function doesn't have a return statement, so even if it works, 
 
    // it returns undefined 
 
} 
 

 
function multiple(num) { 
 
    var splitNumbers = num.toString().split(''); 
 
    var a = splitNumbers[0]; 
 
    var b = splitNumbers[1]; 
 
    return a * b; 
 
} 
 

 
console.log(persistence(39));

所以修复代码:

function persistence(num) { 
 
    var total = 1; 
 
    var step = 0; 
 
    var number = multiple(num); 
 
    // Make splitNumbers available locally 
 
    var splitNumbers = String(number).split(''); 
 

 
    while (step < 3) { 
 
    // Use the length of splitNumbers, not number 
 
    for (var i = 0; i < splitNumbers.length; i++) { 
 
     total *= splitNumbers[i]; 
 
    } 
 
    multiple(number); 
 
    step += 1; 
 
    } 
 
    // Return the accumulated step count 
 
    return step; 
 
} 
 

 
function multiple(num) { 
 
    var splitNumbers = num.toString().split(''); 
 
    var a = splitNumbers[0]; 
 
    var b = splitNumbers[1]; 
 
    return a * b; 
 
} 
 

 
console.log(persistence(39));

但是没有使用递归,你使用顺序编程,它的运行速度比递归快(虽然不一定明显),但通常是更多的代码。

其他的答案显示出一些很好的替代解决方案,下面是一个使用最新功能(递归):

function persistence(num, steps = 0) { 
 
    if (num > 9) steps++; 
 
    var total = (num || 0).toString().split('').reduce((a, b) => a * b); 
 
    return total > 9? steps += persistence(total) : steps; 
 
} 
 

 
[39, 999, 4].forEach(function(num) { 
 
    console.log(num + ' : ' + persistence(num)); 
 
});

+0

谢谢您的详细解释! – NZMAI

+0

哦,你提供了解决方案。我尽量避免查看可行的代码。但是,这没关系!没关系))) – NZMAI