• FreeCodeCamp( FCC)前端工程师 中级算法练习 分析与解答


    说在前面

    这是要一篇非常简单的新手能看懂的文章,希望你喜欢。由于在 freecodecamp 中貌似!?无法使用 ES6 的某些语法,未测试具体。所以基本上用古老?!ES5,4写成,谢谢。在写本博文前没有参考过别人的做法,纯手打,我的方法肯定不是最好,只是以我自己喜欢的方式在写而已。

    纯原创,转载请联系作者https//:wusuai1995@qq.comgivingwu@gmail.com

    • freecodecamp China
    • 不明白API参考MDN给出的解释
    • 个别题目没有判断函数参数及其类型,仅通过了Run tests
    • 如果你最近在写微信小程序蓝牙的话请参考wx-bluetooth
    • 有疑惑请留言

    开始

    Sum All Numbers in a Range

    1. 先对传入数组升序排列,拿到 [min, max]
    2. 然后 generateArr 成一个 [min, min+1, min+2, ..., max]
    3. Array.prototype.reduce 方法从左至右求和
    function sumAll(arr) {
      if (!Array.isArray(arr) || !arr || !arr.length) return;
      arr = arr.sort(function(a, b){ return a-b;});
      arr = generateArr(arr[0], arr[1]);
      console.log(arr);
    
      return arr.reduce(function(accu, curr){
        return accu += curr;
      });
    }
    
    function generateArr(min, max) {
      var arr = [];
      while (min <= max) {
        arr.push(min);
        min++;
      }
    
      return arr;
    }
    

    Diff Two Arrays

    1. 合并两个数组成一个数组
    2. 通过一个 obj 缓存数组中每项的出现次数
    3. 返回 obj[arr[i]] 仅出现一次的项组成的数组
    function diff(arr1, arr2) {
      if (!Array.isArray(arr1) || !Array.isArray(arr2)) return;
      var newArr = arr1.concat(arr2);
    
      return unique(newArr);
    }
    
    function unique(arr) {
      var a = [], i, l, item, key, obj = {};
    
      for (i = 0, l = arr.length; i < l; i++) {
        item = arr[i];
        if (obj[item] === undefined) {
          obj[item] = [item];
        } else {
          obj[item].push(item);
        }
      }
    
      console.log(arr, obj);
    
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (obj[key].length === 1){
            a = a.concat(obj[key]);
          }
        }
      }
    
      return a;
    }
    

    Roman Numeral Converter

    • 先把每个数所对应的阿拉伯数字和罗马数字取出来并一一对应
    var RomanNumArr = [1000, 900, 500,  400, 100,  90,   50,   40,  10,   9,   5,    4,   1],
        RomanNumStrArr = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
    
    • 然后对给出的数进行 倒推求余 的推算并返回对应数字数组,比如139 = [100 + 39] = [100 + 3 * 10 + 9] = [100, 10, 10, 10, 9]
    function getSeparatedRomanNumArr (num, arr) {
      arr = arr || [];
    
      for (var i = 0, l = RomanNumArr.length; i < l; i++) {
        var curr = RomanNumArr[i], next, int;
    
        if (num >= curr) {
          if (num % curr === 0) {
            return pushNumByTimes2Arr(curr, num / curr, arr);
          } else {
            next = num % curr;
            int = num - next;
    
            return getSeparatedRomanNumArr(next, pushNumByTimes2Arr(curr, int / curr, arr));
          }
        }
      }
    }
    
    function pushNumByTimes2Arr(num, times, arr) {
      while (times) {
        arr.push(num);
        times--;
      }
    
      return arr;
    }
    
    • 将每个阿拉伯数字对上罗马数字,然后对返回的数组进行 Array.prototype.join 即可,例如上面例子139 = [100, 10, 10, 10, 9] = ['C', 'X', 'X', 'X', 'IX'].join('') = 'CXXXIX'
    function convert(num) {
      if (!num || 'number' !== typeof +num) throw new TypeError();
      var romanNumArr = getSeparatedRomanNumArr(num);
    
      return romanNumArr.map(function(item){
        return RomanNumStrArr[RomanNumArr.indexOf(item)];
      }).join('');
    }
    

    Where art thou

    1. for loop取出collection中的每个对象的keys然后与source对象的keys进行比对通过函数getSameItems
    2. 将当前 collection[i]key 的与 sameKeys 进行比对,如果全部全等就 match 反正 false
    function where(collection, source) {
      var arr = [], sourceKeys = Object.keys(source), obj, key, objKeys,
          sameKeys, i, l = collection.length, j, k, matched;
    
      for (i = 0; i < l; i++) {
        obj = collection[i];
        objKeys = Object.keys(obj);
    
        if (objKeys.length < sourceKeys.length) continue;
        sameKeys = getSameItems(sourceKeys, objKeys);
     
        if (sameKeys.length < sourceKeys.length) continue;
        matched = true;
    
        if (sameKeys && sameKeys.length) {
          for (j = 0, k = sameKeys.length; j < k; j++) {
            key = sameKeys[j];
    
            if (obj[key] !== source[key]) {
              matched = false;
            }
          }
        }
    
        if (matched) arr.push(obj);
      }
    
      return arr;
    }
    
    function getSameItems (arr1, arr2) {
      if (!arr1 || !arr1.length || !arr2 || !arr2.length) throw new TypeError();
      var arr = [];
      
      arr1.forEach(function(item){
        if (~arr2.indexOf(item)) {
          arr.push(item);
        }
      });
      
      return arr;
    }
    

    Search and Replace

    function myReplace(str, before, after) {
      after = isUpperCase(before[0]) ? camelize(after) : after;
      str = str.replace(before, after);
      return str;
    }
    
    function camelize (str) {
      return str.slice(0, 1).toUpperCase() + str.slice(1, str.length);
    }
    
    function isUpperCase(s) {
      return s === s.toUpperCase();
    }
    

    Pig Latin

    1. 根据题意先写出元音数组vowels,然后分割字符串成数组并比对是否存在元音字符,如果有则立即返回该 index 位置,反之返回 undefined
    2. 如果 index === 0 则返回 str + 'way' 反之返回 str.slice(vowelIndex, str.length) + str.substr(0, vowelIndex) + 'ay';
    function translate(str) {
      var vowelIndex = findVowelsIndex(str);
      str = vowelIndex === 0 ? str + 'way' : str.slice(vowelIndex, str.length) + str.substr(0, vowelIndex) + 'ay';
    
      return str;
    }
    
    function findVowelsIndex (str) {
      var vowels = ['a', 'e', 'i', 'o', 'u'];
      var strArr = str.split(''), i, l, index;
      
      for (i = 0, l = strArr.length; i < l; i++) {
        index = vowels.indexOf(strArr[i]);
        if (~index) {
          return i;
        }
      }
    }
    

    DNA Pairing

    function pair(str) {
      var strArr = str.split(''), pairArr = [], pair, i, l;
      
      for (i = 0, l = strArr.length; i < l; i++) {
        switch(strArr[i]){
          case 'C':
            pair = 'G';
            break;
          case 'G':
            pair = 'C';
            break;
          case 'A':
            pair = 'T';
            break;
          case 'T':
            pair = 'A';
            break;
        }
    
        pairArr.push([strArr[i], pair]);
      }
    
      return pairArr;
    }
    

    Missing letters

    1. 比对给出的str的每个字符,并全部转换成
    2. 如果当前字符的 charCode 不等于 nextcharCode 则找到了该 迷失字符
    function fearNotLetter(str) {
      var strArr, i, l, curr, next, noMissing = true;
    
      strArr = str.split('').map(function(word){
        return word.charCodeAt();
      });
      
      for (i = 0, l = strArr.length; i < l; i++) {
        curr = strArr[i];
        next = strArr[i + 1];
    
        console.log('curr:', curr, 'next:', next);
    
        if (i !== l - 1 && ++curr !== next) {
          str = String.fromCharCode(curr);
          noMissing = false;
          break;
        }
      }
    
      return noMissing ? undefined : str;
    }
    

    Boo who

    function boo(bool) {
      // What is the new fad diet for ghost developers? The Boolean.
      if (typeof bool !== 'boolean') return false;
    
      return true;
    }
    

    Sorted Union

    function unite(arr1, arr2, arr3) {
      return Array.prototype.reduce.call(arguments, function(accu, curr){
        console.log('accu:', accu);
        console.log('curr:', curr);
        curr = curr.filter(function(item){
          return !~accu.indexOf(item);
        });
    
        return accu.concat(curr);
      });
    }
    

    Convert HTML Entities

    function convert(str) {
      var i, j, reg, chars = ['&', '<', '>', '"', "'"], strs = ['&amp;', '&lt;', '&gt;', '&quot;', '&apos;'];
      
      for (i = 0, l = chars.length; i < l; i++) {
        reg = new RegExp('\' + chars[i], 'gm');
        str = str.replace(reg, strs[i]);
      }
    
      return str;
    }
    

    Spinal Tap Case

    function spinalCase(str) {
      // "It's such a fine line between stupid, and clever."
      // not, there is a comma still.
      // --David St. Hubbins
      var reg1 = /(s|\_)/g, reg2 = /([A-Z])/g;
      
      if (reg1.test(str)) {
        str = str.replace(reg1, '-');
      } else if (reg2.test(str)) {
        str = str.replace(reg2, '-$1');
      }
      
      str = str.toLowerCase();
    
      return str;
    }
    

    Sum All Odd Fibonacci Numbers

    1. 先拿到斐波那契中所有小于 num 的数
    2. 然后求该数组中所有奇数(odd)项的和
    function sumFibs(num) {
      if (num <= 2) return num;
      var a = 1, b = 1, arr = [a, b], sum = 0, i, l;
    
      while (sum < num) {
        sum = a + b;
        if (sum <= num) arr.push(sum);
        a = b;
        b = sum;
      }
    
      console.log(arr);
    
      num = 0;
    
      for (i = 0, l = arr.length; i < l; i++) {
        if (arr[i] % 2 !== 0) {
          num += arr[i];
        }
      }
      
      return num;
    }
    

    Sum All Primes

    1. 先将所有数组转出来(抱歉这里用了ES6的新方法 Array.from,请参考MDN Array.from
    2. 判断每一个数是否是质数,通过函数isPrime
    function sumPrimes(num) {
      return Array.from({length: num}).map(function(item, index){
        return ++index;
      }).filter(function(item){
        return isPrime(item);
      }).reduce(function(accu, curr){
        return accu += curr;
      });
    }
    
    function isPrime (num) {
      if (num <= 1) return;
      var i, l, prime = true;
    
      for (i = 2, l = num / 2 + 1; i < l; i++) {
        if (num % i === 0) {
          prime = false;
          break;
        }
      }
    
      return prime;
    }
    

    Smallest Common Multiple

    PS: 这又是一个继罗马数字后不错的中级算法题

    先上一波我用到的资料(即思路):

    1. 一个优秀的答案
    2. Git上老外的答案
    3. 如何求最小公倍数,我选用该帖子中 分解质因数法,所以我们得先求出所有的该区间中每个数的质因数数组,然后去重,最后乘上所有数的质因数
    4. 欧几里德算法
    5. 最大公约数
    6. 质因数分解

    一个优秀的答案,同时向欧几里德表示respect

    // *?!
    

    Finders Keepers

    function find(arr, func) {
      var num = 0;
      return arr.filter(func)[0];
    }
    

    Drop it

    PS: 那一段卖队友也是很666,我表示赞同。但辅助会怎么想?

    function drop(arr, func) {
      // Drop them elements.
      var n = arr.shift();
    
      if (n !== undefined) {
        if (!func(n)) {
          return drop(arr, func);
        } else {
          arr.unshift(n);
          return arr;
        }
      } else {
        return [];
      }
    
      return arr;
    }
    

    Steamroller

    function steamroller(arr) {
      // I'm a steamroller, baby 
      var result = [], i, l;
    
      for(i = 0, l = arr.length; i < l; i++){
        if(Array.isArray(arr[i])){
          result = result.concat(steamroller(arr[i]));
        }else{
          result.push(arr[i]);
        }
      }
    
      return result;
    }
    

    Binary Agents

    1. 将二进制字符串参数通过空格切分为数组
    2. 将2进制转为10进制
    3. 通过 String.fromCharCode返回字符串
    function binaryAgent(str) {
      return str.split(/s/g).map(function(s){
        return String.fromCharCode(parseInt(s, 2));
      }).join('');
    }
    

    Everything Be True

    function every(collection, pre) {
      // Is everyone being true?
      return collection.every(function(item) {
        return item[pre];
      });
    }
    

    Arguments Optional

    函数curry化参考JavaScript currying

    function add(a, b) {
      var args = Array.prototype.slice.call(arguments, 0);
    
      if (typeof a !== 'number') return undefined;
      if (args.length < 2) {
        return function (b) {
          if (typeof b !== 'number') return undefined;
          args.push(b);
    
          return add.apply(this, args);
        };
      } else {
        if (typeof b !== 'number') return undefined;
      }
    
      return a + b;
    }
    

    结语

    不算上我做题的时间,我就是复制自己写好的代码也花了一段时间。而且部分题目没有被 freeCodeCamp 记录了,又重新来一次,但只有前几道是。应该是间隔一段时间后,数据会被清掉而只记录是否完成状态。

    表示这个 Smallest Common Multiple 我写的递归未过,所以不贴。

    感谢上面贴出的所有引用连接,如果有任何引用存在问题,请联系作者立即下线。

    观看容易,手打不易,且看且学习。

  • 相关阅读:
    BeautifulSoup 安装使用
    用Mediawiki做百科网站资源大参考
    ubutun 下webalizer 分析Apache日志
    网站流量统计系统 phpMyVisites
    mysql的root密码忘记解决方
    mrtg监控网络流量简单配置
    CentOS 6.4下Squid代理服务器的安装与配置,反向代理
    linux 查看文件系统类型
    JAVA多媒体编程入门(图像部分)
    log4net使用具体解释
  • 原文地址:https://www.cnblogs.com/givingwu/p/8400754.html
Copyright © 2020-2023  润新知