美文网首页
2020-05-19 4 kyu How many number

2020-05-19 4 kyu How many number

作者: 苦庭 | 来源:发表于2020-05-20 22:04 被阅读0次

    My answer / NAC

    function findAll(n, k) {
        var res = [];
        for(let i=Math.pow(10, k-1); i<Math.pow(10, k); i++){
          if(i.toString() == i.toString().split("").sort().join`` && i.toString().split("").reduce((a,b)=>Number(a)+Number(b), 0) == n) res.push(i);
        }
        return res.length ? [res.length, res[0].toString(), res[res.length-1].toString()] : [];
    }
    

    问题出在哪?

    • 直接穷举法对计算机的计算量太大,耗时超过12000ms了
    • 需要优化(递归),这里的递归学问就大了。递归本质上就是循环(能取代一些循环的操作),却胜过循环,简称“套娃”。

    My answer / AC

    function findAll(n, k, min=1) {
        // 判断结束条件
        if(n<k*min || n>k*9) return [];
        if(k==1) return [1, String(n), String(n)];
        // 两种情况会返回,要么要求的sum不可能达到要求(太小了我后面全取最小的都表示不了)
        // 要么太大了,后面全取9都表示不了,这两种都直接返回[]。
        // 而能够表示的,并且只要求一位数字的,直接返回一位所对应的结果。
        
        var count = 0;
        var maximum = "0".repeat(k);
        var minimum = "9".repeat(k);
        for(var i=min; i<=9; i++){
          var cur = findAll(n-i, k-1, min=i);
          if(cur.length>0){
            count += cur[0];
            // (站在最高层想)将弟弟们递归完出来的最大/最小值加上当前字符变成一个新的字符串,
            // 在这些新的字符串里面找到当前的最大值
            // (站在倒数第二层想)将下一个递归完出来并且不为[]的findAll(n-i, 1, i)之结果[1, n-i, n-i]的最大/最小值加上当前字符变成一个新的字符串,
            // 在这些新的字符串里面找到当前的最大值
            minimum = minimum<(i+cur[1])?minimum:i+cur[1];
            maximum = maximum>(i+cur[2])?maximum:i+cur[2];
          }
          
        }
        console.log(count+","+minimum+","+maximum);
        return [count, minimum, maximum];
    }
    
    • 这里findAll(n, k, min)和它的返回值[count, minimum, maximum]是真的得好好看懂的。
    • n是当前轮的总和值,k是当前轮的总位数,min是新加的,表示当前轮能取到最小的数字,方便递归操作,也能够保证我们的数字是从小到大走的。(我本来思路是循环,没想这里使用递归来将位数不断逼小,直到k为1,而循环是没有这种路越走越窄最后变成if(k===1)这种单独判断的,这也是为什么说递归胜过循环了)

    递归的上下文(stack frame)会切换,循环不会切换(位于相同的 stack frame)

    from hoodlum1980
    • count是当前轮递归满足要求的总个数,minimummaximum分别是当前轮最小值和当前轮最大值

    Best answer

    function findAll(n,k,min=1) {
      if(n<min*k || n>9*k)
        return [];
      if(k===1)
        return [1,String(n),String(n)];
      var counter=0;
      var minimum="9".repeat(k);
      var maximum="0".repeat(k);
      for(var i=min;i<=9;i++){
        var current=findAll(n-i,k-1,i);
        if(current.length>0){
          counter+=current[0];
          if(i+current[1]<minimum)
            minimum=i+current[1];
          if(i+current[2]>maximum)
            maximum=i+current[2];
        }
      }
      return [counter,minimum,maximum];
    }
    

    好在哪?

    • 用了递归,加了新参数。优化了性能,避免爆服务器。

    Recap

    • 多做点递归,熟悉递归的上下文相关的写代码方式

    相关文章

      网友评论

          本文标题:2020-05-19 4 kyu How many number

          本文链接:https://www.haomeiwen.com/subject/rquiohtx.html