【问题标题】:Javascript, a simple recursive functionJavascript,一个简单的递归函数
【发布时间】:2020-04-04 19:45:18
【问题描述】:

我需要帮助来实现一个递归函数。这是我第一次尝试在我们新手首先学习的标准“阶乘”之外进行递归。

我能够在控制台中得到正确的答案,但我不知道如何让我的函数识别出它已经产生了正确的答案。

挑战:“编写一个算法来确定一个数字是否“快乐”。

一个快乐的数字是由以下过程定义的数字:从任何正整数开始,将数字替换为其数字的平方和,并重复该过程,直到数字等于 1(它将保持不变),或者它在一个不包括 1 的循环中无限循环。这个过程以 1 结束的那些数字是快乐数字。”

我的尝试:

let num = 19;

let isHappy = (n) => {

  let sNum = `${n}`;
  let sArray = sNum.split('');
  let nArray = sArray.map(el => Number(el))
  let total = nArray.reduce((acc, curr) => {
  return acc += curr * curr
}, 0);
  if(isHappy(total) === 1) {
    return true
  } else {
   return false
  }
}

isHappy(num)

我在执行基本案例测试时使用了 while 循环并进行了不同的尝试,但没有运气。任何帮助将不胜感激。

【问题讨论】:

  • 你有一些数字的例子吗?他们是否满意?
  • 对不起,我忘了添加测试变量(num=19),很高兴
  • 您需要提供周期检测,即。使用您之前尝试过的所有数字的集合

标签: javascript recursion


【解决方案1】:

您可以先返回给定号码的支票(退出早期方法),然后使用Set 来查看号码

  • 如果有,很高兴返回true
  • 是之前看到的数字,然后你得到一个循环,然后返回false
  • 或返回递归调用的结果以及所有数字的平方和。

function isHappy(value, seen = new Set) {
    if (value === 1) return true;
    if (seen.has(value)) return false;
    seen.add(value);
    return isHappy(value.toString().split('').reduce((s, d) => s + d * d, 0), seen);
}

console.log(isHappy(1));
console.log(isHappy(19));
console.log(isHappy(4));
console.log(isHappy(22));

【讨论】:

  • 要求是:用其数字的平方之和替换数字
  • 我认为现在是正确答案 :) 顺便说一句,否决票不是我的。
  • 所有这些答案都让我迷失了,使用的概念或符号太高级 atm('new Set'、'symbol'、Map 等),但感谢您的帮助。
  • 使用@NinaScholz 方法得到它,第一次使用不仅仅是标准初始化数组或对象的数据结构。现在感觉不那么失败了,非常感谢。
【解决方案2】:

这是一种无需使用先前看到的数字列表即可计算答案的方法。

// This function calculates the next number in the sequence from the current number.
const digitSquareSum = n => {
  let sum = 0;
  let num = n;

  while (num > 0) {
    const rem = num % 10;
    num = (num - rem) / 10;
    sum += rem * rem;
  }

  return sum;
};

// Floyd's hare and tortoise algorithm is used to detect cycles in a sequence.
const floyd = (f, n) => {
  let tortoise = f(n);
  let hare = f(f(n));

  while (hare !== tortoise) {
    tortoise = f(tortoise);
    hare = f(f(hare));
  }

  return hare;
};

// If the number in the cycle is 1 then the number is happy.
const isHappy = n => floyd(digitSquareSum, n) === 1;

console.log(isHappy(1));  // true
console.log(isHappy(19)); // true
console.log(isHappy(4));  // false
console.log(isHappy(22)); // false

与 Nina 的 answer 不同,此解决方案具有内存效率。

【讨论】:

  • 感谢您的帮助,我会努力掌握弗洛伊德算法
【解决方案3】:

这是@Nina 答案的全局缓存版本

const emotion_unknown = Symbol('emotion_unknown');
const happy_cache = new Map;
happy_cache.set(1, true);

function isHappy(value) {
  if (happy_cache.has(value)) {
    if (happy_cache.get(value) == emotion_unknown) return false
    else return happy_cache.get(value)
  }
  //optional: only set cache for value < 1000 since next(999)<1000
  //there should be a tighter bound, but 1000 is not large :P
  //and you can use an array for bounded cache
  let next = value.toString().split('').reduce((s, d) => s + d * d, 0)
  happy_cache.set(value, emotion_unknown)
  let result = isHappy(next)
  happy_cache.set(value, result)
  return result
}

//the SO console seems to have 50 line limit
//for (let i = 1; i < 100; ++i) {if (isHappy(i)) console.log(i);}
let happy_numbers=new Set;
for (let i = 1; i < 1000; ++i) {if (isHappy(i)) happy_numbers.add(i);}
console.log(...happy_numbers)

【讨论】:

  • 感谢您的意见,让我知道我需要学习“符号”和“新地图”,我以前从未遇到过这些术语
  • 很高兴为您提供帮助 :) 简短描述:Symbol 创建一个唯一的对象,Map 是一个将一个值映射到另一个值的容器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 2021-11-28
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 2016-05-08
相关资源
最近更新 更多