2017-02-26 206 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