JavaScript 错误:函数 returns NaN 即使 typeof 函数 returns "number"

JavaScript bug: function returns NaN even though typeof function returns "number"

我想找出 给定 数字排列的最大数字。

如果给定的数是123,那么它的最大排列数是321。

编辑

我通过更改

取得了一些进步
if (str.length === 0) return "";
if (str.length === 1) return str;

if (str.length === 0) {
    return "";
} else {
    return str;
}

然而,问题仍然存在:函数 returns 一个字符串。实际上,数组成员是 strings 而不是 numbers.

function findPerms(num) {
    var str = num.toString();
    
  if (str.length === 0) {
        return "";
    } else {
        return str;
    }
 
  let result = [];
  for (let i = 0; i < str.length; i++) {
    const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1);
    for (let j = 0; j < remainingChars.length; j++) {
      result.push(Number(currentChar + findPerms(remainingChars)[j]));
    }
  }

    result.sort(function(a, b) {
        return a - b;
    });

  return result[result.length - 1];
    
}


console.log(findPerms(11121));
console.log(typeof findPerms(11121));

为此我做了:

function findPerms(num) {
  var str = num.toString();

  if (str.length === 0) return "";
  if (str.length === 1) return str;
  let result = [];
  for (let i = 0; i < str.length; i++) {
    const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1);
    for (let j = 0; j < remainingChars.length; j++) {
      result.push(Number(currentChar + findPerms(remainingChars)[j]));
    }
  }

  result.sort(function(a, b) {
    return a - b;
  });

  return result[result.length - 1];

}

console.log(findPerms(11121));
console.log(typeof findPerms(11121));

问题

我一定是犯了一个我无法发现的错误,因为上面的函数 returns NaN (尽管 typeof findPerms(11121) returns “数”)。

我哪里错了?

编辑
我想这就是你想要做的。
使用递归生成一个数字的所有数字排列的数组。
对数组进行排序。
Return最大数的排列。

这可以通过将问题分解为两个函数来完成。
第一个函数returns一个数字所有排列的数组。
第二个函数从第一个函数获取数组结果,然后对其进行排序。然后它 returns 最后一个值。
您的递归操作不正确。这就是它不起作用的原因。

<html><head><title>6770990</title>
<script>
function findPerms(num) {
  var str = num.toString(); var result = [];
  if (str.length == 0) return result;
  if (str.length == 1) return [parseInt(str)];
  for (var i = 0; i < str.length; i++) {
    const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1)
    var perms = findPerms(remainingChars) //----Permutation array of remaining chars.
    for (var j = 0; j < perms.length; j++) {
      result.push(parseInt("" + currentChar + perms[j]));
    }
  }
  return result; //----All permutations for num.
}
function findLargestPerm(num)
{ var perms = findPerms(num); perms.sort(function(a,b) {return a-b;});
  return perms[perms.length-1];
}
</script>
</head></body>
<script>
var r = findLargestPerm(11121); alert("r=" + r);
</script>
</body></html>

上一个回答

将数字倒序排列并连接成一个数字会更有效。这将是最大的排列。

函数 findPerms() 试图找到一组数字的最大排列。有时将函数重命名为它的作用会有所帮助,这样更容易遵循逻辑。

再次使用递归调用函数的那一行只需要为每个当前字符调用一次。

以下代码显示了发生的步骤。

<html><head><title>6770990</title>
<script>
var msg="";
function findLargestPermutation(num)
{ var str = num.toString(); msg += "findLargestPermutation(" + str + ")<br>";
  if (str.length === 0) return "";
  if (str.length === 1) return str;
  let result = [];
  for (let i = 0; i < str.length; i++)
  { const currentChar = str[i];
    const remainingChars = str.slice(0, i) + str.slice(i + 1);
    msg += "currentChar=" + currentChar + " remainingChars=" + remainingChars + "<br>";
    //----The j loop should be removed and just use this line.
    var num = Number(currentChar + findLargestPermutation(remainingChars));
    msg += "num=" + num + "<br>";
    result.push(num);
  }
  result.sort(function(a, b) {return a - b;});
  msg += "findLargestPermutation()=" + result[result.length - 1] + "<br>";
  return result[result.length - 1];
}
</script>
</head><body>
<div id="div"></div>
<script>
var lp = findLargestPermutation(11121);
alert("lp=" + lp + " typeof lp=" + typeof lp);
document.getElementById("div").innerHTML = msg;
</script>
</body></html>

您的代码存在一些问题,但让我们先尝试正确定义需求。 如果我理解你想要做的是找到一个数字的所有排列和 select 数字中数字的最高可能排列。 你想要做的是这样的:

  1. 创建一个空列表
  2. 遍历初始数字的数字。
  3. 对于每个数字循环遍历剩余的数字并找到所有可能的组合并将它们添加到初始空列表中。
  4. 在列表中列出所有可能的数字组合后,对它们进行排序,return 最高的结果。

这里有2个问题,首先代码的执行有一些错误,你的算法不是很高效。 让我们来解决第一个问题: 当您创建结果列表时,您将其定义在递归函数内,这意味着在每次递归调用时它将被一个空数组覆盖。通常,当您应用此技术时,您要么在递归函数之外定义结果数组,要么将其作为参数传递,以便能够迭代结果。 您似乎没有很好地了解函数范围以及闭包在 JS 中的工作方式。为此,我建议阅读 MDN 上的一些资源。

这里的另一个问题是您希望该函数接收一个数字作为参数,但是当您在

中调用它时
result.push(Number(currentChar + findPerms(remainingChars)

remainingChars 是一个字符串,因此结果为 NaN。

接着说第二个问题。考虑到您想要从一系列数字中获得最大可能的数字,您可以将数字从最高到最小排序并提供结果。 例如: 如果数字是 18,你可以将它排序成 [8, 1] 这样的数组,然后将它连接到 81。 该代码可能看起来像:

function findHighestPerm(no) {
  const arr = no.toString().split('');
  return parseInt(arr.sort((a, b) => b - a).join(''));
}

PS:我知道我的代码不是最高效或最优雅的,但我只是懒惰而且它有效;)