While loop running after return true?

问题描述 投票:0回答:1

我正在实施 HAPPY NUMBER,但无法弄清楚为什么我的 WHILE 循环永远不想停止执行?我知道这对于像 2 这样的少数输入情况会失败,这就是为什么我计划将所有总和存储在一个数组中,然后检查是否有任何数字正在执行只会导致无限循环。

var storeNum = [];
var isHappy = function(n) {
    while(n > 1){
        n = findSum(n);
        storeNum.push(n);
    }
    if(n == 1){
       console.log("HAPPY NUMBER");
       return true;
    }
    return false;
};

function findSum(n) {
    let sum = 0;
    while(n != 0){
        let rem = Math.floor(n % 10);
        sum = sum + rem * rem;
        n = n/10;
    }
    return sum;
}
loops while-loop logic dsa
1个回答
0
投票

不明白为什么我的 WHILE 循环永远不想停止执行?

嗯,这是预料之中的。代码挑战说:

重复这个过程,直到数字等于 1(它将停留的位置),或者它循环无限循环不包括 1.

这就是你的代码中发生的事情:它在一个循环中无限循环。您的代码需要检测存在cycle

我计划将所有总和存储在一个数组中,然后检查是否有任何数字正在执行只会导致无限循环。

你不应该这样做later,因为当你陷入无限循环时就没有了。当检测到循环时,您应该中断循环。

所以循环条件应该有一个额外的检查。为了使其正常工作,循环体应首先将数字添加到集合中,然后才计算下一个值:

    while(n > 1 && !storeNum.includes(n)){
        storeNum.push(n);
        n = findSum(n);
    }

另一个问题是你的数组是一个全局变量,这意味着在你的函数的第二次调用中,第一次调用的值仍然在那个数组中。这不是你想要的。而是将该数组定义为局部变量:

    const storeNum = [];
    while(n > 1 && !storeNum.includes(n)){
        storeNum.push(n);
        n = findSum(n);
    }

现在可以用了。

您仍然可以通过以下方式提高此解决方案的效率:

  • 避免

    findSum
    中的浮点计算,因为目前除以10在大多数情况下不是整数。也受益于
    +=
    运营商:

    const rem = n % 10;  // No more need of floor()
    sum += rem * rem;    // Can use += operator
    n = (n - rem) / 10;  // Make sure the result is integer
    
  • 使数组成为一个集合。这样查找速度更快:

    const storeNum = new Set;
    while(n > 1 && !storeNum.has(n)){
        storeNum.add(n);
        n = findSum(n);
    }
    
  • 保留以前调用的结果。

    为此,全局变量 很有用。它可以是具有布尔值的地图。我们已经可以用一个条目初始化这张地图:1 是一个快乐的数字。

这导致这段代码:

const memo = new Map;
memo.set(1, true);

var isHappy = function(n) {
    const storeNum = new Set;
    while(!storeNum.has(n) && !memo.has(n)) {
        storeNum.add(n);
        n = findSum(n);
    }
    const result = !!memo.get(n); // This will be false when not in memo
    // All numbers in the traversed path have same outcome
    for (const m of storeNum) memo.set(m, result);
    return result;
};

function findSum(n) {
    let sum = 0, rem;
    while (n != 0) {
        rem = n % 10;
        sum += rem * rem;
        n = (n - rem) / 10;
    }
    return sum;
}
© www.soinside.com 2019 - 2024. All rights reserved.