【问题标题】:Seeking help on explanation for a big combination algorithm寻求帮助解释一个大的组合算法
【发布时间】:2020-01-16 17:48:07
【问题描述】:

最近的CodeSignal Challenge 是计算 1000C500 (mod 1e9+7),结果我输了。

我所有的试验都超过了时间限制。这是best JS solution by psr。谁能解释这一行发生了什么?我学习了 ES6,但不知道它的语法 f[o = n + 1/k] = o in f ...

f = nCk = (n, k) => f[o = n + 1/k] = o in f
    ? ...
    : ... 
        ? n && ...
        : ...

有些行被屏蔽以避免违反规则

【问题讨论】:

  • o = n + 1/k; f[o] = o in f; 的缩写。
  • 请注意,Stack Overflow 几乎没有关于从任何地方发布代码的规则。您从中复制代码的地方可能有禁止从其站点复制代码的规则。通过在此处复制代码,您将根据 CC-by-SA 4.0 许可(重新)许可代码。 “psr”可能对此感到满意,也可能不满意。
  • @Barmar 谢谢,但我仍然对f[o] = o in f 感到困惑o 是新分配的小数,f[o]=o 是将 o 分配到 f 的属性 o 中?并检查它是否是in f ?? @HereticMonkey 谢谢提醒,屏蔽几行可以吗?
  • o in f 被用作三元表达式中的条件。因此,如果o 已经是f 对象中的一个键,则它分配一个值,如果这是一个新键,则分配一个不同的值。
  • 这在使用对象属性作为计数器时很常见;您第一次将计数器初始化为1,随后将其递增。

标签: javascript math combinations


【解决方案1】:

感谢Barbar在问题评论中的解释,我现在了解算法了。

算法可以改写如下:

f = nCk = (n, k) => {   //Declare both f and nCk as the same function
let o = n + 1/k         //o will be the key of function object f
f[o] = o in f           //Define f[o] based on a nested ternary expression
    ? f[o]              //Avoid recalculation if f has key o already 
    : k==0              //nC0 is always 1
        ? 1
        : n<k           //nCk is improper and assigned 0 if n<k
            ? 0
            : f(--n, k) //Do recursion nCk = (n-1)Ck + (n-1)C(k-1)
            + f(n, k - 1) 
return f[o]             //Done!
}

这是一个 5C2 的例子

f(n,k)  n   k   o   f[o]
f(5,2)  5   2   5.5 f[5.5]=f(4,2)+f(4,1)=10
f(4,2)  4   2   4.5 f[4.5]=f(3,2)+f(3,1)=6
f(3,2)  3   2   3.5 f[3.5]=f(2,2)+f(2,1)=3
f(2,2)  2   2   2.5 f[2.5]=f(1,2)+f(1,1)=1
f(1,2)  1   2   1.5 f[1.5]=f(0,2)+f(0,1)=0
f(0,2)  0   2   0.5 f[0.5]=0
f(0,1)  0   1   1   f[1]=0
f(1,1)  1   1   2   f[2]=f(0,1)+f(0,0)=1
f(0,0)  0   0   Inf f[Inf]=1 //Inf aka Infinity
f(2,1)  2   1   3   f[3]=f(1,1)+f(1,0)=2
f(1,0)  1   0   Inf f[Inf]=1
f(3,1)  3   1   4   f[4]=f(2,1)+f(2,0)=3
f(n,0)  n   0   Inf f[Inf]=1
f(4,1)  4   1   5   f[5]=f(3,1)+f(3,0)=4

附:在研究这个算法时,我得到了一些收获

  1. 在同一行上双重声明函数作为递归技巧

  2. 立即使用刚刚分配值的键

  3. Infinity 可以用作对象的键(!)

  4. 语法o in f检查对象f是否有键o

【讨论】:

  • 使原始代码令人困惑的是它使用了如此紧凑的格式。如果你把它拆分成单独的语句,添加临时变量,将三元组更改为 if/else,它会变得清晰得多。
  • 它还混淆地使用函数本身作为对象来存储数据。它是故意写的让人困惑。
  • @Barmar 规则只考虑权限和代码长度,碰到这个解决方案我很震惊^^"
猜你喜欢
  • 2011-09-22
  • 1970-01-01
  • 2010-11-04
  • 2021-05-27
  • 2021-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多